Posts Tagged ‘Java EE’
Let’s handle the database via the sourcecode
Before we could connect to the database, we have edit persist.xml file to configure EclipseLink to connect to the database. When you use the default configuration for EclipseLink, then you should have to edit a lot in that file.
It looks a bit like this:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="com.rivaso_exp" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>/jdbc/expdb</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="eclipselink.ddl-generation.output-mode" value="database"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> </properties> </persistence-unit> </persistence>
And then we should make a connector to it: This is easy done with an entity manager.
To achieve that, we have to make an abstract class which covers many the basic actions you want to do on a database like counting, getting the highest used id (which is definitely not the same as the amount of entities in your table!), create, edit and remove.
Make a class like this:
package com.rivaso.exp.facade; import java.util.List; import javax.persistence.EntityManager; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; /** * @author RiVaSo * @version 1.0 */ public abstract class AbstractManager { private Class entityClass; public AbstractManager(Class entityClass) { this.entityClass = entityClass; } protected abstract EntityManager getEntityManager(); public void create(T entity) { getEntityManager().persist(entity); } public void edit(T entity) { getEntityManager().merge(entity); } public void remove(T entity) { getEntityManager().remove(getEntityManager().merge(entity)); } public T find(Object id) { return getEntityManager().find(entityClass, id); } @SuppressWarnings ({"rawtypes", "unchecked"}) public List findAll() { javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder(). createQuery(); cq.select(cq.from(entityClass)); return getEntityManager().createQuery(cq).getResultList(); } @SuppressWarnings ({"rawtypes", "unchecked"}) public List findRange(int[] range) { javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder(). createQuery(); cq.select(cq.from(entityClass)); javax.persistence.Query q = getEntityManager().createQuery(cq); q.setMaxResults(range[1] - range[0]); q.setFirstResult(range[0]); return q.getResultList(); } @SuppressWarnings ({"rawtypes", "unchecked"}) public int count() { javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder(). createQuery(); javax.persistence.criteria.Root rt = cq.from(entityClass); cq.select(getEntityManager().getCriteriaBuilder().count(rt)); javax.persistence.Query q = getEntityManager().createQuery(cq); return ((Long) q.getSingleResult()).intValue(); } @SuppressWarnings ({"rawtypes", "unchecked"}) public int getCurrentMaxOfId() { javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder(). createQuery(); javax.persistence.criteria.Root rt = cq.from(entityClass); cq.select(getEntityManager().getCriteriaBuilder().max(rt.get("id"))); javax.persistence.Query q = getEntityManager().createQuery(cq); Object result = q.getSingleResult(); if (result == null) { return 0; } return ((Integer) result).intValue(); } }
Then extend that abstract class with your own class which you want to use, like for example PersonManager:
package com.rivaso.exp.manager; import com.rivaso.exp.domain.Person; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author RiVaSo * @version 1.0 */ @Stateless(name = "PersonManager") public class PersonManager extends AbstractManager<Person> { private static Logger log = LoggerFactory.getLogger(PersonManager.class); @PersistenceContext(unitName = "com.rivaso_exp") private EntityManager em; @Override protected EntityManager getEntityManager() { return em; } public PersonManager() { super(Person.class); } public Person getPersonByEmail(String personEmail) { try { return (Person) em .createQuery("SELECT OBJECT(Person) FROM Person person WHERE person.emailAddress = :personEmail") .setParameter("personEmail", personEmail).getSingleResult(); } catch (NoResultException e) { log.warn("Person could not be found"); } catch (Exception e) { log.warn("Could not get PersonByMail", e); } return null; } }
Let’s use JPA now – Part 2: Defining Columns
After we made and understand how to make Tables from our classes, let’s continue by annotating their member variables.
Firstly, you have to keep this in mind:
JPA could only convert primitive datatypes of Java in primitive datatypes of SQL. Objects made of self-brewed classes can only be written directly to the database with the special annotation @Embeddable, or you have to create a special table for them, like we did earlier.
Generic Annotations:
@Transient
Use this annotation when you don’t want that EclipseLink saves the variable to the database. For example converters such as SimpleDateFormat. EclipseLink will pass this member variable and doesn’t make a column for this one.
@Id
The annotation for defining the variable as the primary key of the table. It’s recommended to add at each class a special member-variable when the class has its own table.
@GeneratedValue
The annotation which is recommended for the member-variable which is also annotated with @Id, unless you want to handle the index-value of the entries of the table by yourself.
@NotNull
Handy when you want to enforce that every entry has a value at that column. Please notice that you’ll also get bugged when a 0 is inserted/updated at a column with the INTEGER datatype, because it’s also counted as ‘not null’.
@Null
Contrary of @NotNull, every value is allowed. Is the default setting at each member variable when @NotNull nor @Null is annotated.
@Column (name = “email_address”)
An annotation to add more specific properties for the member value.
It could be very useful, for example since databases doesn’t like the lowerCamelCase- nor UpperCamelCase-style, like:
@NotNull
private String emailAddress;
Should be:
@Column (name = "email_address", nullable=false)
private String emailAddress;
For member variables which are used as primary keys, you could also use it like this:
@Id
@GeneratedValue
@Column (unique = true, nullable = false)
private int id;
In this case the “unique” keyword of @Column says that each value of column should be unique and can’t be used twice in the table.
Type-specific annotations:
@ElementCollection
This one is required for variables which have collections as type.
Please remember that you can’t use direct collection implementations like HashMap, ArrayList, HashSet!
Always use their interface, like Map, List and Set, and use the implementation of the variables at their initialisation!
@Embedded
Use this annotation when the type of the variable is a self-defined class, which don’t have its own table.
The object assigned to this variable will be serialized and saved into the column.
@Temporal
This annotation is used when the type is java.util.Date and java.util.Calendar.
Note that you also have to include an attribute value, like @Temporal(TemporalType.TIMESTAMP), @Temporal(TemporalType.DATE) and @Temporal(TemporalType.TIME).
@Enumerated
Use this annotation when the type of the variable is an ENUM. Please note that ‘ENUM-classes’ don’t have any annotation.
Done with that?
The next thing that we’ll do is talking to your database via the sourcecode.
Let’s use JPA now Part 1: Creating Tables
We make a travel in time. And now we’re at the point that we made a domain model for the logic of our application. Of course, you could indeed build a GUI with Wicket first, it’s a bit what you like the most. In this blogpost I assume you’ve build a working domain model. But now, we have to save our precious data in a database. Instead of building a database with a database-generation program, -or even more dramatically- writing it in PLAIN SQL. We don’t want that because it’s too much work, and time. Instead of that, we’re using JPA (previously known as Hibernate).
What you’ll need:
– A few basic classes
– Configured your IDE to work with an Persistence Service, Like OpenJPA, TopLink or EclipseLink. The latter one is packed and preconfigured in NetBeans.
You could use JPA via an apart XML file or do it with Annotations in your code. It’s up to you which method you like the most, I’m covering the method for using Annotations because I find apart XML files harder to maintain.
There are various things you could define with Annotations.
Let’s start now.
If you want to give your domain class a own table use the annotation @Entity above the define statement of your class, like this:
package com.rivaso.exp.domain; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Table; /** * * @author RiVaSo * @version 1.0 */ @Entity @Table( name = "person" ) public class Person implements Serializable { // More code goes here }
As you could see, there is also an annotation included called @Table, where you define that it has a primairy table, in this case the table “Person”.
Please notice that the parameter ‘name = “person”‘ wasn’t needed, because it’s more used to give the Classes who are written in camelcase, a nickname for the database to distinguish them from other classes and SQL-keywords.
Ok, done that. What’s next?
Annotating the member values of the class…so we could define the columns.
I want to develop a java-ee-maven-wicket-postgresql application on Windows!
What you’ll need:
– A windows environment ( WinXP or Win7 are recommended )
– A ‘recently enough’ version of JDK of Java. ( 6u29 )
– A ‘recently enough’ version of PostgreSQL ( 9.1.0-1 )
– A ‘recently enough’ version of Netbeans ( 7.0.1 )
– A ‘recently enough’ version of Maven 2, Standalone installer(because accessing the build-in maven of netbeans via cmd is surprisingly hard ). ( 3.0.3 )
– A ‘recently enough’ version of Wicket ( 1.5.3 )
Begin with installing the JDK, I’m using version 1.6u29, since I’ve read rumours about that version 7 isn’t stable enough yet. Time will tell. I didn’t tried to install Java EE SDK including Glassfish, because NetBeans has an embedded Glassfish instance at its own.
Please note that you don’t have to install pgAdmin ( the admin tool for your PostgreSQL DB ), it’s already included in the PostgreSQL installer.
Note that you’ve to unpack Maven by yourself, and don’t forget to add it to your (system) path of your system environment, create also two new system environment variables: JAVA_HOME ( preferably C:\Program Files\Java\jre6\ WITHOUT quotes ) and CLASSPATH ( .;%JAVA_HOME%\lib ).