Configuration
Maven
When using a database, JPA, and integration of JPA and Spring, we should
add following dependencies based on chapter 9's configuration: (We add
spring-web
and cblib
for Spring framework which is explained in
previous chapter.)
<properties>
<zk.version>8.0.0-Eval</zk.version>
<maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
<packname>-${project.version}-FL-${maven.build.timestamp}</packname>
<spring.version>3.1.2.RELEASE</spring.version>
</properties>
...
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<!-- JPA(Hibernate) and HSQL dependencies -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.2.6</version>
</dependency>
...
- Line 5, 16~17: Spring provides a module to integrate several ORM (Object Relation Mapping) frameworks, integrating JPA requires this dependency.
- Line 27~28: There are various implementations of JPA specification, we choose Hibernate's one which is the most popular.
- Line 32~33: For using HSQL, we should add its JDBC driver.
Persistence Unit Configuration
We should describe persistence unit configuration in an XML file called
persistence.xml
and we need to specify name
, transaction-type
, and
properties
. The properties
are used by persistence provider
(Hibernate) to establish database connection and setup vendor specific
configurations.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="myapp" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.connection.driver_class"
value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.connection.url"
value="jdbc:hsqldb:file:data/store" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
</persistence-unit>
</persistence>
- Line 3: The persistence unit name
myapp
will be used later in Spring configuration.
Deployment Descriptor
You aren't required to add any special configuration for JPA to work.
Here we add a Spring provided OpernEntityMangerInViewFilter
to resolve
an issue caused by lazy-fetching in one-to-many mapping. Please refer to
Developer's
Reference
for this issue in more detail.
Extracted from web.xml
...
<!-- Spring configuration -->
<!-- Initialize spring context -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Enable webapp Scopes-->
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<filter>
<filter-name>OpenEntityManagerInViewFilter
</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
Entity Annotation
Before storing objects into a database, we should specify OR (object-relation) mapping for Java classes with meta data. After JDK 5.0, we can specify OR mapping as annotations instead of XML files. JPA supports configuration by exception which means that it defines default for most cases of application and users only need to override the configuration value when it is exception to the default, not necessary.
First, annotate the class with @Entity
to turn it into an entity, and
annotate the member field for primary key with @Id
. All other
annotations are optional and we use them to override default values.
Todo class used in todo-list management
@Entity
@Table(name="apptodo")
public class Todo implements Serializable, Cloneable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer id;
boolean complete;
@Column(nullable=false,length=128)
String subject;
@Column(nullable=false,length=128)
@Enumerated(EnumType.ORDINAL)
Priority priority;
@Temporal(TemporalType.TIMESTAMP)
Date date;
String description;
//omit getter, setter, hashCode(), equals() and other methods
}
Spring Beans Configuration
Spring JPA , available under the org.springframework.orm.jpa
package,
offers integration support for Java Persistence API. According to Spring
framework reference, there are three options for JPA setup. We choose
the simplest one.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="org.zkoss.essentials" />
<!-- jpa(hibernate) configuration -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myapp"/>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven />
</beans>
- Line 16,17: The simplest Spring setup for JPA is to add a
LocalEntityManagerFactoryBean
which create aEntityManagerFactory
for simple deployment environments and specify itspersistenceUnitName
property. - Line 18: Set property
persistenceUnitName
with the name we specified inpersistence.xml
. - Line 21,26: Enable Spring's declarative transaction management.