Hibernate 3.5.0-CR-2/JPA 2.0 - Getting Started
Version 2.0 of the Java Persistency API (JPA), a.k.a JSR-317, was released a while ago (10-December-2009) and Hibernate's next version (3.5.0) will implement this version of the specification. In this, and the next, blog entries I'm planning to explorer JPA 2.0 new features and Hibernate implementation of those feature. Since this is the first post in the series I'll focus on environment setup and include only few new mapping options:
The Hibernate documentation says that starting of 3.5.0 Hibernate annotations and Entity Manager are bundled with Hibernate Core (see comment in the Binary Releases table here). However after building my Eclipse workspace out of my POM (mvn eclipse:eclipse) I've noticed that I am still missing the Hibernate Annotations/Entity Manager classes. After an hour of wondering around I've noticed that the Hibernate Core 3.5.0-CR-2 JAR in Jboss' repository does not bundle the Annotations and Entity Manager but when downloading the same distribution from hibernate site it does include both project's classes within. It is a little bitconfusing but the bottom line is simple: we still have to include these projects as dependencies in the POM. An explanation can be found here:"It means that they now live in the same SVN project, now share the same release cycle, use the same version numbers and get bundled into the same release bundle (the stuff available from SourceForge). Hibernate Core aims to be modular to isolate dependencies as much as possible in terms of transitive dependencies for your projects. Hibernate Core has quite a few jars."
The second dependency which needs special treatment is the ejb3-persistence, as usual these are not included on the Maven Central repository and needed to be downloaded from the JCP site and installed into the local repository. After solving these two dependencies issue (and configuration the JBoss' repository – as illustrated above) my old Hibernate/JPA 1.0 code was running using the new libraries.
The earlier version of the specification didn't define any standard property names in the persistence.xml properties section, leaving all properties to be vendor specific. This version defines a small set of standard properties. Vendors are expected to understand these properties and they can continue support their own specific properties. The specification partition the standard properties into two groups - the first group (which I am planning to cover in future posts) is intended to be used both in Java EE and java SE environment the second group is intended to be used in Java SE environment only. The second group includes a set of properties to configure our database connection (the property names talk for themselves):
The old Hibernate equivalent properties are still supported but to fully confirm with the specification I changed my settings to the following (the comment at the start of the sample contains the old configuration):
Up to here is was all environmental and setup issues, the interesting ones are the new mapping features included in the specification. There are quite a few new annotations in JPA 2.0, to keep this post in a reasonable length I'll start with few of them and I'll continue on my next posts. I'll try to start with the "basic" ones (by saying "basic" I mean some changes and enhancements to JPA 1.0 existing mapping support, these are usually a standardization of features already existing in previous Hibernate/TopLink versions using their specific annotations).
In the previous version of the JPA specification we didn't have any equivalent to the Hibernate's DELETE_ORPHAN cascade type ("private ownership" in TopLink), JPA 2.0 defines such behavior using the orphanRemoval attribute on the ManyToOne and OneToMany annotations. The specification defines the orphanRemoval behavior in two different scenarios:
Here is a one-to-many example
Another new addition to JPA is an equivalent to Hibernate's CollectionOfElements annotation: @ElementCollection this annotation can be used to map a collection of basic types or embeddable objects. Here is an example of the most basic form of this mapping
The above maps the collection of basic types (String) as an attribute of the Customer entity, the mapping of the hobbies collection will use the following defaults:
By default the column name of the embedded data is derived from the attribute names of the embedded class or from the collection attribute name for a basic type. This can be overridden using the @AttributeOverride for embedded classes or @Column for basic types:
We can also customize the table name using the new @CollectionTable annotation. This annotation can be used to change the table name (by default the concatenation of the name of the containing entity and the name of the collection attribute separated by an underscore) and the join column. The defaults in my case are good enough but just for the example:
Here is an example with a bag of embeddables
This is it for the first post in the series, on next posts I'll cover some more new mapping options.
- The orphanRemoval option
- The ElementCollection annotaiotn, and
- The CollectionTable annotation
My Environment
- Hibernate 3.5.0-CR-2 (Please notice that Hibernate 3.5 is still a candidate release so things written in this blog entry might change in the future)
- Database PostgreSQL 8.3
Migrating My Environment
The first thing I have to do is to migrate my environment to use the new libraries, on this step I don't plan any change to the code (unless I have to) all that I'm planning to do is to update my Maven POM, build the project and make sure that my old JUnit tests are still working. Here are the relevant dependencies and repositories from my POM:
<dependencies>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>ejb3-persistence</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.5.0-CR-2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.0-CR-2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.5.0-CR-2</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.9.0.GA</version>
<scope>runtime</scope>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.10</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jboss</id>
<name>JBoss repository</name>
<url>http://repository.jboss.org/maven2</url>
</repository>
</repositories>
The Hibernate documentation says that starting of 3.5.0 Hibernate annotations and Entity Manager are bundled with Hibernate Core (see comment in the Binary Releases table here). However after building my Eclipse workspace out of my POM (mvn eclipse:eclipse) I've noticed that I am still missing the Hibernate Annotations/Entity Manager classes. After an hour of wondering around I've noticed that the Hibernate Core 3.5.0-CR-2 JAR in Jboss' repository does not bundle the Annotations and Entity Manager but when downloading the same distribution from hibernate site it does include both project's classes within. It is a little bitconfusing but the bottom line is simple: we still have to include these projects as dependencies in the POM. An explanation can be found here:"It means that they now live in the same SVN project, now share the same release cycle, use the same version numbers and get bundled into the same release bundle (the stuff available from SourceForge). Hibernate Core aims to be modular to isolate dependencies as much as possible in terms of transitive dependencies for your projects. Hibernate Core has quite a few jars."
The second dependency which needs special treatment is the ejb3-persistence, as usual these are not included on the Maven Central repository and needed to be downloaded from the JCP site and installed into the local repository. After solving these two dependencies issue (and configuration the JBoss' repository – as illustrated above) my old Hibernate/JPA 1.0 code was running using the new libraries.
Standard Properties
The earlier version of the specification didn't define any standard property names in the persistence.xml properties section, leaving all properties to be vendor specific. This version defines a small set of standard properties. Vendors are expected to understand these properties and they can continue support their own specific properties. The specification partition the standard properties into two groups - the first group (which I am planning to cover in future posts) is intended to be used both in Java EE and java SE environment the second group is intended to be used in Java SE environment only. The second group includes a set of properties to configure our database connection (the property names talk for themselves):
- javax.persistence.jdbc.driver (Hibernate specific equivalent is: hibernate.connection.driver_class)
- javax.persistence.jdbc.user (Hibernate specific equivalent is: hibernate.connection.username)
- javax.persistence.jdbc.password (Hibernate specific equivalent is: hibernate.connection.password)
- javax.persistence.jdbc.url (Hibernate specific equivalent is: hibernate.connection.url)
The old Hibernate equivalent properties are still supported but to fully confirm with the specification I changed my settings to the following (the comment at the start of the sample contains the old configuration):
<!-- Using Hibernate Specific Properties
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
<property name="hibernate.connection.username" value="blog" />
<property name="hibernate.connection.password" value="123321" />
<property name="hibernate.connection.url" value="jdbc:postgresql://127.0.0.1:5432/blog" />
-->
<!-- Using the New Standard Properties -->
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.user" value="blog" />
<property name="javax.persistence.jdbc.password" value="123321" />
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://127.0.0.1:5432/blog" />
New Annotations and Mapping Options
Up to here is was all environmental and setup issues, the interesting ones are the new mapping features included in the specification. There are quite a few new annotations in JPA 2.0, to keep this post in a reasonable length I'll start with few of them and I'll continue on my next posts. I'll try to start with the "basic" ones (by saying "basic" I mean some changes and enhancements to JPA 1.0 existing mapping support, these are usually a standardization of features already existing in previous Hibernate/TopLink versions using their specific annotations).
Removing orphans using the orphanRemoval attribute
In the previous version of the JPA specification we didn't have any equivalent to the Hibernate's DELETE_ORPHAN cascade type ("private ownership" in TopLink), JPA 2.0 defines such behavior using the orphanRemoval attribute on the ManyToOne and OneToMany annotations. The specification defines the orphanRemoval behavior in two different scenarios:
- If the target entity was removed from the owner collection (one to many) or set as null, or other entity (one to one) it will be removed from the database during a flush operation.
- If the parent (owning) entity is removed from the persistency unit the target entity will be removed as well (in other words, when the orphanRemoval attribute is set to true there is no need to specify cascade=REMOVE on the same relation - it is implied by the orphanRemoval)
Here is a one-to-many example
@OneToMany(mappedBy="customer",cascade=CascadeType.PERSIST, fetch=FetchType.LAZY, orphanRemoval=true)
@BatchSize(size=100)
private Set<Order> orders = new HashSet<Order>();
Mapping a collection of elements using the ElementCollection annotation
Another new addition to JPA is an equivalent to Hibernate's CollectionOfElements annotation: @ElementCollection this annotation can be used to map a collection of basic types or embeddable objects. Here is an example of the most basic form of this mapping
public class Customer {
....
@ElementCollection
private Collection<String> hobbies = new HashSet<String>();
The above maps the collection of basic types (String) as an attribute of the Customer entity, the mapping of the hobbies collection will use the following defaults:
- The table name will be 'customer_hobbies'
- The table will have two columns: 'customer_id' - the id of the owning customer and 'hobbies' with the value. A table row will be created for each element in the collection
By default the column name of the embedded data is derived from the attribute names of the embedded class or from the collection attribute name for a basic type. This can be overridden using the @AttributeOverride for embedded classes or @Column for basic types:
public class Customer {
....
@ElementCollection @Column(name="HOBBY_DATA")
private Collection<String> hobbies = new HashSet<String>();
We can also customize the table name using the new @CollectionTable annotation. This annotation can be used to change the table name (by default the concatenation of the name of the containing entity and the name of the collection attribute separated by an underscore) and the join column. The defaults in my case are good enough but just for the example:
public class Customer {
....
@ElementCollection
@Column(name="HOBBY_NAME")
@CollectionTable(name="HOBBIES", joinColumns=@JoinColumn(name="CUSTID"))
private Collection<String> hobbies = new HashSet<String>();
Here is an example with a bag of embeddables
@ElementCollection
@CollectionTable(name="CUST_ADDITIONAL_ADDRS")private List<Address> additionalAddresses = new ArrayList<Address>();
This is it for the first post in the series, on next posts I'll cover some more new mapping options.
Comments
Hyderabad Packers and Movers
Mumbai Packers and Movers
Pune Packers and Movers