![]() |
| The hsqldb table "USER" |
Spring Framework supports JPA very well. This post will show you a very simple example of using JPA under Spring Framework.
Let's say we want to save and access some information of users - a very common use case. We assume a hsqldb database table "USER" with the fields of "ID", "ADDRESS", "DOB", "NAME" for simplicity. This is illustrated in the figure with one record inserted.
Creating the above table (hsqldb) can be done by the following SQL
CREATE TABLE user (
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL,
ADDRESS VARCHAR(255),
DOB DATE,
NAME VARCHAR(255),
PRIMARY KEY (ID))
For this table, we create the following java entity class which some JPA annotations (such as @Entity @Table, @Id and etc).
package com.mytechtip.example.springjpatest; import java.io.Serializable; import java.lang.String; import java.util.Date; import javax.persistence.*; /** * Entity implementation class for Entity: User * */ @Entity @Table(name="user") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private long id; private String name; private String address; @Temporal(TemporalType.DATE) private Date dob; public User() { super(); } public long getId() { return this.id; } public void setId(long id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getAddress() { return this.address; } public void setAddress(String address) { this.address = address; } public Date getDob() { return this.dob; } public void setDob(Date dob) { this.dob = dob; } }
You also need a file called "persistence.xml" placed in folder META-INF. The file contains the following content. It just defines the persistence provider (we use eclipselink) and the entity class
<?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="spring-jpa-test" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>com.mytechtip.example.springjpatest.User</class> </persistence-unit> </persistence>
Then we can define some data access operations such as save, or query. Such methods can be grouped in a Data Access Object (DAO) class as shown below. This UserDao class just defines two operations for demonstration purpose. Some notes below:
- This class is annotated with @Repository so the Spring Framework can be configured to scan the class for auto wired stuff and etc.
- The methods are annotated with @Transactional so it ensures ALL or NOTHING operations (especially for write operations)
- EntityManager em is annotated with @PersistenceContext so Spring Framework can inject the container-managed entity manager.
package com.mytechtip.example.springjpatest; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @Repository public class UserDao { private static final int ONE_YEAR = 1000 * 60 * 60 * 24 * 365; @PersistenceContext EntityManager em; @Transactional public User save(User u) { // some business logic if (u.getName()==null) { throw new IllegalArgumentException("Name can not be null"); } if (u.getDob()==null) { throw new IllegalArgumentException("Dob can not be null"); } if ((System.currentTimeMillis()-u.getDob().getTime())< 10 * ONE_YEAR) { throw new IllegalArgumentException("Must be 10+ year older"); } return em.merge(u); } @Transactional public List<User> getNameStartsWith(String namePrefix) { String query = "select u from User u where u.name like :prefix " + "order by u.name"; Query q = em.createQuery(query); q.setParameter("prefix", namePrefix+ "%"); return q.getResultList(); } }
Now, it's time to wire them up using a beans configuration file as most of Spring Framework applications do. The content of the beans.xml is as follows.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!-- Enable the component scan (auto wiring etc) for the following package --> <context:component-scan base-package="com.mytechtip.example.springjpatest" /> <!-- Make sure the following is specified to enable transaction --> <tx:annotation-driven /> <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- This defines the entity manager factory with some custom properties --> <bean id='entityManagerFactory' class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'> <property name="persistenceUnitName" value="spring-jpa-test"/> <property name='dataSource' ref='dataSource' /> <property name="jpaPropertyMap"> <map> <entry key="eclipselink.weaving" value="false"/> </map> </property> </bean> <!-- This defines the hsqldb data source --> <bean id='dataSource' class='org.springframework.jdbc.datasource.DriverManagerDataSource'> <property name='driverClassName' value='org.hsqldb.jdbc.JDBCDriver' /> <property name='url' value='jdbc:hsqldb:file:spring_jpa_test_db' /> <property name='username' value='sa' /> <property name='password' value='' /> </bean> </beans>
We've now done the most work. Next step is how to run it to see whether it works. Here comes the following java code that can test the methods we've created. It basically saves a user record and do a query to find list of users with name starting with "J".
package com.mytechtip.example.springjpatest; import java.util.Calendar; import java.util.List; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserDao dao = context.getBean(UserDao.class); User u = new User(); u.setAddress("my address"); u.setName("John Smith II"); Calendar cal = Calendar.getInstance(); cal.set(2001, 0, 1); u.setDob(cal.getTime()); dao.save(u); List<User> list = dao.getNameStartsWith("J"); for (User user : list) { System.out.println(u.getName()); } context.close(); } }
If you want to try the example, now you can download the entire project from github.

No comments:
Post a Comment