Object-relational Mapping using Java Persistence API / JPA 2

October 11th, 2010 by

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..

 

Prerequisites

  • Java 6 JDK
  • Maven >= 2
  • If you’d like to take a look behind the scenes e.g. how entities are mapped in your database you could install a RDBMS of your choice .. or just use Derby/JavaDB that is bundled with the JDK 6

JUnit Basics

I am going to run all programming examples as unit tests – this way it is easier to to validate the results. Here is a short introduction of the JUnit annotations used:

  • To include JUnit in your project just add the following dependency to your pom.xml
    <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.8.1</version>
     <scope>test</scope>
    </dependency>
  • @Test: This is what makes your class a test class – just annotate a public method with return type void with @Test and you are able to run it as unit test
  • @Before: A public method with return type void with this annotation is executed before each single test is run
  • @After: Same as above but after each test execution
  • @BeforeClass: A public static method with return type void with this annotation is run when the test class is instanciated
  • @AfterClass: Same as above but after all tests have finished
  • Running your unit tests with Maven is done with
    mvn test

Project Setup

  • Create a new simple Maven project using
    mvn archetype:generate # or
    mvn archetype:create
  • Add the following dependencies and repositories to your pom.xml and ensure Java 6 compliance
    <dependencies>
    	<dependency>
    		<groupId>org.apache.derby</groupId>
    		<artifactId>derbyclient</artifactId>
    		<version>10.6.1.0</version>
    	</dependency>
    	<dependency>
    		<groupId>org.apache.derby</groupId>
    		<artifactId>derby</artifactId>
    		<version>10.6.1.0</version>
    		<scope>test</scope>
    	</dependency>
    	<dependency>
    		<groupId>junit</groupId>
    		<artifactId>junit</artifactId>
    		<version>4.8.1</version>
    		<scope>test</scope>
    	</dependency>
    	<dependency>
    		<groupId>org.hibernate</groupId>
    		<artifactId>hibernate-entitymanager</artifactId>
    		<version>3.5.1-Final</version>
    	</dependency>
    	<dependency>
    		<groupId>org.slf4j</groupId>
    		<artifactId>slf4j-simple</artifactId>
    		<version>1.5.10</version>
    	</dependency>
    </dependencies>
    <repositories>
    	<repository>
    		<id>maven2-repository.dev.java.net</id>
    		<name>Java.net Repository for Maven</name>
    		<url>http://download.java.net/maven/2/</url>
    		<layout>default</layout>
    	</repository>
    	<repository>
    		<id>repository.jboss.org</id>
    		<name>JBoss Public Maven Repository</name>
    		<url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
    	</repository>
    </repositories>
    <build>
    	<plugins>
    		<plugin>
    			<groupId>org.apache.maven.plugins</groupId>
    			<artifactId>maven-compiler-plugin</artifactId>
    			<configuration>
    				<source>1.6</source>
    				<target>1.6</target>
    			</configuration>
    		</plugin>
    	</plugins>
    </build>

Setting the Persistence Provider

  • In this tutorial I am going to focus on annotation based configuration – the only XML we’re going to create is the basic persistence config..
  • Create a new file named persistence.xml in src/test/resources/META-INF
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <persistence-unit name="hascode-manual" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:derby:hascode_testdb;create=true"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        </properties>
    </persistence-unit>
    </persistence>
  • For this tutorial we are going to use Hibernate as persistence provider – if you prefer using EclipseLink (fka TopLink) .. first add these dependencies to your pom.xml
    <dependencies>
     <dependency>
     <groupId>org.eclipse.persistence</groupId>
     <artifactId>javax.persistence</artifactId>
     <version>1.1.0</version>
     </dependency>
     <dependency>
     <groupId>org.eclipse.persistence</groupId>
     <artifactId>eclipselink</artifactId>
     <version>1.1.0</version>
     </dependency>
     [..]
    </dependencies>
     
    <repositories>
     [..]
     <repository>
     <id>EclipseLink Repo</id>
     <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
     <snapshots>
     <enabled>true</enabled>
     </snapshots>
     </repository>
    </repositories>
  • Then change the provider and the parameters in the persistence.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
     version="1.0">
     <persistence-unit name="hascode-manual" transaction-type="RESOURCE_LOCAL">
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
     <properties>
     <property name="eclipselink.target-database" value="DERBY" />
     <property name="eclipselink.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
     <property name="eclipselink.jdbc.url" value="jdbc:derby:test2db;create=true" />
     <property name="eclipselink.jdbc.user" value="APPT" />
     <property name="eclipselink.jdbc.password" value="APPT" />
     <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
     <property name="eclipselink.logging.level" value="FINE" />
     </properties>
     </persistence-unit>
    </persistence>
  • Back to the configuration using Hibernate .. at last my pom.xml looks like this
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.hascode.tutorial.jpa2</groupId>
     <artifactId>jpa2-tutorial</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     
     <dependencies>
     <dependency>
     <groupId>org.apache.derby</groupId>
     <artifactId>derbyclient</artifactId>
     <version>10.6.1.0</version>
     </dependency>
     <dependency>
     <groupId>org.apache.derby</groupId>
     <artifactId>derby</artifactId>
     <version>10.6.1.0</version>
     <scope>test</scope>
     </dependency>
     <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.8.1</version>
     <scope>test</scope>
     </dependency>
     <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-entitymanager</artifactId>
     <version>3.5.1-Final</version>
     </dependency>
     <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-simple</artifactId>
     <version>1.5.10</version>
     </dependency>
     </dependencies>
     <repositories>
     <repository>
     <id>maven2-repository.dev.java.net</id>
     <name>Java.net Repository for Maven</name>
     <url>http://download.java.net/maven/2/</url>
     <layout>default</layout>
     </repository>
     </repositories>
     <build>
     <plugins>
     <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <configuration>
     <source>1.6</source>
     <target>1.6</target>
     </configuration>
     </plugin>
     </plugins>
     </build>
    </project>

Basic Mapping

  • The easiest way to persist a class is to create a plain old java object (POJO) and then use annotations to define the persistence rules.
  • In this example we’re going to persist our first class so create a new class named Person in the package com.hascode.tutorial.jpa2
    package com.hascode.tutorial.jpa2;
     
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
     
    @Entity
    public class Person {
     @Id
     @GeneratedValue
     private Long    id;
     
     private String    nickname;
     
     private String    email;
     
     public Long getId() {
     return id;
     }
     
     public void setId(Long id) {
     this.id = id;
     }
     
     public String getNickname() {
     return nickname;
     }
     
     public void setNickname(String nickname) {
     this.nickname = nickname;
     }
     
     public String getEmail() {
     return email;
     }
     
     public void setEmail(String email) {
     this.email = email;
     }
     
    }
  • 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:
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
     version="1.0">
     <persistence-unit name="hascode-manual" transaction-type="RESOURCE_LOCAL">
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
     <class>com.hascode.tutorial.jpa2.Person</class>
     <properties>
     <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
     <property name="javax.persistence.jdbc.url" value="jdbc:derby:hascode_testdb;create=true" />
     <property name="hibernate.show_sql" value="true" />
     <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
     <property name="hibernate.hbm2ddl.auto" value="create-drop" />
     </properties>
     </persistence-unit>
    </persistence>
  • Now we want to test if the mapping nad the persistence is working so create a test class named PersonTest and the package com.hascode.tutorial.jpa2 in src/test/java
    package com.hascode.tutorial.jpa2;
     
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNotNull;
     
    import java.sql.SQLException;
     
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
     
    import org.junit.AfterClass;
    import org.junit.Before;
    import org.junit.BeforeClass;
    import org.junit.Test;
     
    public class PersonTest {
     private static EntityManagerFactory    emf;
     private static EntityManager        em;
     private static EntityTransaction    tx;
     
     @Before
     public void initEntityManager() throws Exception {
     emf = Persistence.createEntityManagerFactory("hascode-manual");
     em = emf.createEntityManager();
     tx = em.getTransaction();
     }
     
     @After
     public void closeEntityManager() throws SQLException {
     em.close();
     emf.close();
     }
     @Test
     public void testPersist() {
     tx.begin();
     Person person = new Person();
     person.setNickname("mickey");
     person.setEmail("mickey@testhost.moby");
     em.persist(person);
     tx.commit();
     
     // look if the entity was persisted and got an id assigned
     assertNotNull(person.getId());
     
     // lookup entity
     Long id = person.getId();
     Person userFromDatabase = em.find(Person.class, id);
     assertNotNull(userFromDatabase);
     assertEquals("mickey", userFromDatabase.getNickname());
     assertEquals("mickey@testhost.moby", userFromDatabase.getEmail());
     }
    }
  • Now run the test – there should be no errors ..
  • So what is happening here?
  • @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.
    @Transient
    String 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
    package com.hascode.tutorial.jpa2;
     
    public enum 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)
    @Enumerated
    private Sex    sex;
  • Finally add a new test method to the existing test class PersonTest
    @Test
     public void testEnum() {
     tx.begin();
     Person person = new Person();
     person.setNickname("mickey");
     person.setSex(Sex.FEMALE);
     em.persist(person);
     tx.commit();
     
     Long id = person.getId();
     Person userFromDatabase = em.find(Person.class, id);
     
     assertEquals(Sex.FEMALE, userFromDatabase.getSex());
     }

Dates/Calendars

  • JPA allows you to specify the representation of a Date or Calendar object in the database using the @Temporal annotation
  • Lets add a birthday to our Person class  (don’t forget the getter and setter) – we’re not interested in seconds so we’re going to use TemporalType.Date
    @Temporal(TemporalType.DATE)
    private Date birthday;
  • Finally add another test method to the test class
    @Test
     public void testDate() {
     tx.begin();
     final Date date = new Date();
     Person person = new Person();
     person.setNickname("mickey");
     person.setBirthday(date);
     em.persist(person);
     tx.commit();
     
     Long id = person.getId();
     Person userFromDatabase = em.find(Person.class, id);
     
     assertEquals(date, userFromDatabase.getBirthday());
     }

Basic Collections

  • For mapping collections of basic java types there is @ElementCollection to define a basic collection combined with @CollectionTable to define the table where the values are stored
  • In our example we want to save a generic list of strings as a list of hobbies in the Person class – so add this field and the setters and getters
    @ElementCollection()
    @CollectionTable(name = "Hobbies")
    private List<String>    hobbies;
  • And another test method to our test class
    @Test
     public void testHobbies() {
     tx.begin();
     Person person = new Person();
     person.setNickname("mickey");
     final List<String> hobbies = new ArrayList<String>();
     hobbies.add("Coding");
     hobbies.add("Not sleeping");
     hobbies.add("drinking coffee");
     hobbies.add("living the cliché");
     person.setHobbies(hobbies);
     em.persist(person);
     tx.commit();
     
     Long id = person.getId();
     Person userFromDatabase = em.find(Person.class, id);
     
     assertEquals(4, userFromDatabase.getHobbies().size());
     }

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”)
    package com.hascode.tutorial.jpa2;
     
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
     
    @Entity
    public class Address {
     @Id
     @GeneratedValue
     private Long    id;
     private String    street;
     private String    city;
     public Long getId() {
     return id;
     }
     public void setId(Long id) {
     this.id = id;
     }
     public String getStreet() {
     return street;
     }
     public void setStreet(String street) {
     this.street = street;
     }
     public String getCity() {
     return city;
     }
     public void setCity(String city) {
     this.city = city;
     }
    }
  • Register the address class in your persistence.xml by adding <class>com.hascode.tutorial.jpa2.Address</class>
  • Add the relation to the address to the Person class
    @OneToOne
    private Address            address;
  • Testing ..
    @Test
     public void testAddress() {
     tx.begin();
     
     Address address = new Address();
     address.setCity("Paris");
     address.setStreet("Rue de St. Denis");
     em.persist(address);
     
     Person person = new Person();
     person.setNickname("mickey");
     person.setAddress(address);
     em.persist(person);
     tx.commit();
     
     Long id = person.getId();
     Person userFromDatabase = em.find(Person.class, id);
     
     assertEquals("Paris", userFromDatabase.getAddress().getCity());
     }

One-to-Many Relations

  • Our person has some bookmarks so create a bookmark class first
    package com.hascode.tutorial.jpa2;
     
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
     
    @Entity
    public class Bookmark {
     @Id
     @GeneratedValue
     private Long    id;
     
     private String    title;
     
     private String    url;
     
     public String getTitle() {
     return title;
     }
     
     public void setTitle(String title) {
     this.title = title;
     }
     
     public String getUrl() {
     return url;
     }
     
     public void setUrl(String url) {
     this.url = url;
     }
     
     public Long getId() {
     return id;
     }
     
     public void setId(Long id) {
     this.id = id;
     }
    }
  • Add the reference to the bookmark class in the persistence.xml by adding <class>com.hascode.tutorial.jpa2.Bookmark</class>
  • In the next step add fields, getter and setter to the person class
    @OneToMany
    private List<Bookmark>    bookmarks;
  • Update the test class
    @Test
     public void testBookmarks() {
     tx.begin();
     
     Bookmark b1 = new Bookmark();
     b1.setTitle("A website");
     b1.setUrl("https://www.hascode.com");
     
     Bookmark b2 = new Bookmark();
     b2.setTitle("Another website");
     b2.setUrl("https://www.hascode.com/tag/jpa2");
     em.persist(b1);
     em.persist(b2);
     
     List<Bookmark> bookmarks = new ArrayList<Bookmark>();
     bookmarks.add(b1);
     bookmarks.add(b2);
     
     Person person = new Person();
     person.setNickname("mickey");
     person.setBookmarks(bookmarks);
     em.persist(person);
     tx.commit();
     
     Long id = person.getId();
     Person userFromDatabase = em.find(Person.class, id);
     
     assertEquals("A website", userFromDatabase.getBookmarks().get(0)
     .getTitle());
     }

Many-to-Many Relations

  • Finally our person should have some pets .. and pets should have many persons as owners ..
  • Add a new class named Pet
    package com.hascode.tutorial.jpa2;
     
    import java.util.List;
     
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.ManyToMany;
     
    @Entity
    public class Pet {
     @Id
     @GeneratedValue
     private Long            id;
     
     private String            name;
     
     @ManyToMany(mappedBy = "pets")
     private List<Person>    owner;
     
     public String getName() {
     return name;
     }
     
     public void setName(String name) {
     this.name = name;
     }
     
     public Long getId() {
     return id;
     }
     
     public void setId(Long id) {
     this.id = id;
     }
     
     public List<Person> getOwner() {
     return owner;
     }
     
     public void setOwner(List<Person> owner) {
     this.owner = owner;
     }
    }
  • Add the declaration to your persistence.xml <class>com.hascode.tutorial.jpa2.Pet</class>
  • Add a list of pets to the person class
    @ManyToMany()
    private List<Pet>        pets;
  • And a unit test
    @Test
     public void testPet() {
     tx.begin();
     
     Pet pet1 = new Pet();
     pet1.setName("Nanny the bunny");
     Pet pet2 = new Pet();
     pet2.setName("Doggie Dog");
     
     List<Pet> pets = new ArrayList<Pet>();
     pets.add(pet1);
     pets.add(pet2);
     
     Person p1 = new Person();
     p1.setNickname("Mickey");
     p1.setPets(pets);
     
     Person p2 = new Person();
     p2.setNickname("Minny");
     p2.setPets(pets);
     
     em.persist(pet1);
     em.persist(pet2);
     em.persist(p1);
     em.persist(p2);
     tx.commit();
     
     assertNotNull(pet1.getId());
     
     Person userFromDB = em.find(Person.class, p1.getId());
     assertEquals(2, userFromDB.getPets().size());
     }

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.

We’re adding some JPQL samples for the existing Person class to our test class

@Test
public void testJPQL() {
	tx.begin();
 
	Bookmark b1 = new Bookmark();
	b1.setTitle("Snoring for experts");
	b1.setUrl("https://www.hascode.com");
 
	em.persist(b1);
 
	List<Bookmark> bookmarks = new ArrayList<Bookmark>();
	bookmarks.add(b1);
 
	Person hal = new Person();
	hal.setNickname("HAL9000");
	hal.setBookmarks(bookmarks);
	em.persist(hal);
	em.flush();
	tx.commit();
 
	// query with named parameters (i prefer this one)
	TypedQuery<Person> query = em.createQuery(
			"SELECT p FROM Person p WHERE p.nickname=:name", Person.class);
	query.setParameter("name", "HAL9000");
	Person p1 = query.getResultList().get(0);
	assertEquals(hal.getId(), p1.getId());
 
	// same with positional parameters
	TypedQuery<Person> query2 = em.createQuery(
			"SELECT p FROM Person p WHERE p.nickname=?1", Person.class);
	query2.setParameter(1, "HAL9000");
	Person p2 = query2.getResultList().get(0);
	assertEquals(hal.getId(), p2.getId());
 
	// an example using joins
	TypedQuery<Person> query3 = em
			.createQuery(
					"SELECT p FROM Person p LEFT JOIN FETCH p.bookmarks b WHERE b.title=:title",
					Person.class);
	query3.setParameter("title", "Snoring for experts");
	Person p3 = query3.getResultList().get(0);
	assertEquals(hal.getId(), p3.getId());
}

Named Queries

With named queries you are able to bind queries to an entity and use them later via the EntityManager’s createNamedQuery method

  • We’re going to add two named queries to our Person class .. if you’re going to define more than one named query per entity you must wrap them within an @NamedQueries() annotation
    @Entity
    @NamedQueries({
     @NamedQuery(name = "findAll", query = "SELECT p FROM Person p"),
     @NamedQuery(name = "findByNickname", query = "SELECT p FROM Person p WHERE p.nickname=:name")})
    public class Person {
      [..]
    }
  • And another test method to do some querying ..
    @Test
    public void testNamedQueries() {
    	tx.begin();
    	Person donald = new Person();
    	donald.setNickname("Donald");
     
    	Person ronald = new Person();
    	ronald.setNickname("Ronald");
     
    	em.persist(donald);
    	em.persist(ronald);
    	tx.commit();
     
    	List<Person> persons = em.createNamedQuery("findAll", Person.class)
    			.getResultList();
    	assertEquals(2, persons.size());
     
    	Query q = em.createNamedQuery("findByNickname");
    	q.setParameter("name", "Ronald");
    	Person isItRonald = (Person) q.getResultList().get(0);
    	assertEquals(ronald.getId(), isItRonald.getId());
    }

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 :)

So lets add a type safe shiny criteria search to out unit test

@Test
 public void testCriteriaApi() {
 tx.begin();
 Person donald = new Person();
 donald.setNickname("Donald");
 
 Person ronald = new Person();
 ronald.setNickname("Ronald");
 
 em.persist(donald);
 em.persist(ronald);
 tx.commit();
 
 CriteriaBuilder cb = em.getCriteriaBuilder();
 CriteriaQuery<Person> cq = cb.createQuery(Person.class);
 Root<Person> pr = cq.from(Person.class);
 cq.where(cb.equal(pr.get("nickname"), "Ronald"));
 TypedQuery<Person> typedQuery = em.createQuery(cq);
 List<Person> persons = typedQuery.getResultList();
 assertEquals(ronald.getId(), persons.get(0).getId());
 
 }

Fetching Strategies

There are two possible fetching strategies for mapped relations:

  • 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
  • You are able to check out the example code from the Bitbucket.org repository (you should have Mercurial installed first)
    hg clone https://hascode@bitbucket.org/hascode/jpa2_tutorial

Other JPA Articles

Please feel free to have a look at my other articles about the Java Persistence API:

Resources

Article Updates

  • 2015-03-03: Links to other JPA articles added.

    Tags: , , , , , , , , , , , , , , , ,

    One Response to “Object-relational Mapping using Java Persistence API / JPA 2”

    1. Fran Says:

      What about Many to One relations?

      and Join examples will be great too :)

      Good job.

      Fran

    Search
    Categories