Object-relational Mapping using Java Persistence API / JPA 2

Today we’re going to take a look at the world of object-relational Mapping and how it is done using the Java Persistence API by creating some basic examples, mapping some relations and querying objects using JPQL or the Criteria API..

Open the persistence.xml decribed above and add the following element to the persistence-unit node: <class>com.hascode.tutorial.jpa2.User</class> .. if you’re going to use Hibernate and Derby your src/test/resources/META-INF/persistence.xml should look like this:

@Entity makes the class an entity, every field is persisted in a table named “PERSON”. The table name is derived from the class name an my be overridden like that: @Table(name=”person_table”). If you don’t want a field to be saved in the database then make use of the @Transient Annotation e.g.

@TransientString email;

@Id marks the field id as the primary key in the RDBMs and @GeneratedValue instructs the persistence provider to generate a value. There are different generation strategies to choose @GeneratedValue(strategy=GenerationType.AUTO). There are several generation types available like IDENTITY, SEQUENCE, TABLE.

In the persistence.xml is declared which persistence provider is used, the database connection details and that we’re managing the transactions by hand (transaction-type=”RESOURCE_LOCAL”) – when working with EJBs you might want to set the transaction-type to “JTA” but for our examples we’re doing manually .. that’s why we need to begin and commit our transactions explicitly.

Mapping Special Types

Enums

Lets say there is an enum describing the user’s sex that should be mapped .. the enum is named Sex

packagecom.hascode.tutorial.jpa2;publicenum Sex {
MALE, FEMALE
}

JPA offers the annotation @Enumerated to handle enums. You may specify how to write the enum to the database .. to use it’s ordinal number (EnumType.ORDINAL) or to use its name (EnumType.STRING) so we would add this field to the User class (+getter and setter)

Mapping Relations

One-to-One Relations

Use the @OneToOne annotation to map a unary relation

In our example a person has one address so we’re creating a new class Address in this example the access is unidirectional if you’d like to access the person from the address entity you’d need to add a field Person person in the Address class and annotate it with @OneToOne(mappedBy=”address”)

Querying

In the preceding examples we used the EntityManager’s find(Class, Object) method to retrieve an object by its primary key. Of course there are other possibilities to create more complex queries to the persistence layer – lets start with JPQL ..

JPQL

If you’re used to the Hibernate Query Language (HQL), JPQL should not be a problem. As HQL. JPQL is a SQL like abstraction but works on entities instead of tables.

Criteria API

Using the new criteria API prevents some disadvantages of JPQL .. one the one hand it is not type safe (getResultList() returns an untyped list ) on the other hand you are able to create invalid queries because you construct them by passing a string to the createQuery method. For more detailed information about the criteria API I recommend reading chapter 6 in the JSR-317 blueprints

Fetching Strategies

Eager Fetching: Related objects are loaded when the original entity is loaded

Lazy loading: The related objects are fetched later e.g. by a called getter

There are different default fetching strategies for the different relation types

One-to-One: Eager

Many-to-One: Eager

One-to-Many: Lazy

Many-to-Many: Lazy

If you want to define the fetching strategy for mapped relations you may do this like that

@OneToMany(fetch=FetchType.EAGER)private List<Bookmark> bookmarks;

Conclusion

We have left out a lot of other interesting features like inheritance mapping, versioning, bidirectional mappings and ordering instructions. If you’re interested in these then take a look at the linked resources

This entry was posted
on Monday, October 11th, 2010 at 7:54 pm and is filed under Java.
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.