Spring and JPA
Yes, the chapter is really long. We have explained in detail on the integration of Spring with Hibernate and iBatis. I cannot ignore Java Persistence API (JPA) in this chapter which details data access methodologies which Spring supports to be used in your application with ease. This section details the integration of Spring with JPA.
JPA is designed to operate on domain objects and is defined as POJO’s with special annotations which are used as metadata to do the real mapping between the POJO and the actual database tables. It replaces previous persistence mechanisms like EJB entity beans and JDO (Java Data Objects). It provides common API for object-relational mapping and is direct learning from existing products like Hibernate, TopLink, etc. There are some very key concepts that you would like to know before diving deep into Spring and JPA integration. They are:
- EntityManager – this is the resource manager that maintains the active collection of entity objects in your application. It handles the database interaction and meta-data for object-relational mappings. An instance of this actually represents a persistence context. An application can obtain it by injection into the application or by looking it up in the Java component name-space. If the application manages its persistence, the EntityManager is obtained from the EntityManagerFactory.
- EntityManagerFactory – used to create an EntityManager for database interactions. The application server containers typically supply this function, but the EntityManagerFactory is required if you are using JPA application-managed persistence.
- Persistence Unit – consists of the declarative meta-data that describes the relationship of entity class objects to a relational database. The EntityManagerFactory uses this data to create a persistence context that can be accessed through the EntityManager.
The listings in this section show the actual Spring and JPA integration in action. Some steps are identical to Hibernate and iBatis, but I am repeating it as is so that the reader doesn’t have to turn pages and loose the flow of reading. The various steps involved are:
1. Database table creation – create the table according to the database that you are using. Since we have taken Customer entity for explaining this integration example, create the customer table with all the relevant columns. For ease of understanding, I will be using only three fields in the Customer entity namely ‘First Name’, ‘Last Name’ and the primary key ‘ID’. Step same as Hibernate.
2. POJO (Customer) – The Customer POJO containing JPA annotations which provides metadata for linking the POJO and the corresponding database table. The class name is used as table name by default.
Listing 8-53. Customer POJO containing JPA related annotations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
@Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.TABLE) private long id; @Column(name = "first_name") private String firstName; @Column(name = "last_name_name") private String lastName; public Long getId(){ return id; } public void setId(Long id){ this.id = id; } public String getFirstName(){ return firstName; } public void setFirstName(String firstName){ this.firstName = firstName; } public String getLastName(){ return lastName; } public void setLastName(String lastName){ this.lastName = lastName; } public String toString(){ return "Id = " + id + ", First Name = " + firstName + ", Last Name = " + lastName; } } |
3. CustomerRepository interface – the various methods in the interface which the implementation class namely JpaCustomerRepository will implement using JPA.
Listing 8-54. CustomerRepository interface containing relevant methods
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public interface CustomerRepository { public Customer getCustomerById(String customerId); public List getAllCustomers(); public Customer saveCustomer(Customer customer); public Customer updateCustomer(Customer customer); public void deleteCustomer(Customer customer); } |
4. persistence.xml – usually, JPA defines a persistence unit through the META-INF/persistence.xml file. Starting with Spring 3.1, this XML file is no longer necessary – the LocalContainerEntityManagerFactoryBean now supports a ‘packagesToScan’ property where the packages to scan for @Entity classes can be specified. If at all you want to do the old way of doing things in JPA, create a new file namely persistence.xml inside the META-INF folder with the following contents as shown in Listing 8-1 below. You will then have to set the property ‘persistenceUnitName’ while configuring your entity manager.
Listing 8-55. Sample persistence.xml file if you are using Spring earlier than 3.1
1 2 3 4 5 6 7 8 9 |
<?xml version="1.0" encoding="UTF-8" ?> <persistence 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_1_0.xsd" version="1.0"> <persistence-unit name="cargoLoyalty"/> </persistence> |
5. CustomerRepository/CustomerDao implementation class – the Listing 8-56 shows the actual implementation of the CustomerRepository interface using JPA.
Listing 8-56. CustomerRepository implementation class for JPA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public class JpaCustomerRepository extends CustomerRepository { @PersistenceContext EntityManager entityManager; public T getCustomerById( final Long id ){ return this.entityManager.find( this.class, id ); } public List getAllCustomers(){ return this.entityManager.createQuery( "from " + this.class.getName() ).getResultList(); } public void saveCustomer(Customer customer){ this.entityManager.persist(customer); } public void updateCustomer(Customer customer){ this.entityManager.merge(customer); } public void deleteCustomer(Customer customer){ this.entityManager.remove(customer); } } |
6. Spring configuration
a. DataSource configuration – datasource configuration in Spring configuration file. Uses MySql in Listing 8-57.
Listing 8-57. DataSource configuration in Spring configuration
1 2 3 4 5 6 |
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost/loyalty"/> <property name="username" value="loyalty"/> <property name="password" value="password"/> </bean> |
b. EntityManager bean configuration – the main bean which is key to do persistence using JPA. The property namely ‘jpaVendorAdapter’ in Listing 8-58 uses Hibernate JPA, which is one of the implementations of JPA specification. There are other implementations of this, namely:
- EclipseLink
- Apache OpenJPA
- Data Nucleus
- Hibernate EntityManager
Listing 8-58. EntityManager bean configuration
1 2 3 4 5 6 7 8 9 10 11 |
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="com.mybook" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="${hibernate.show_sql}" /> <property name="generateDdl" value="${jpa.generateDdl}" /> <property name="databasePlatform" value="${persistence.dialect}" /> </bean> </property> </bean> |
c. CustomerRepository/CustomerDao configuration – the actual implementation class of CustomerRepository interface is configured.
Listing 8-59. CustomerRepository bean for JPA implementation
1 2 |
<bean id="customerRepository" class=”com.mybook.sample.repositories.JpaCustomerRepository”> </bean> |
7. Testing class – testing class which shows the actual working of Spring and JPA. Usually the consumers of these repositories will the service classes.
Listing 8-60. Testing class for testing Spring and JPA integration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public class SpringJpaTestingClass { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( "applicationContext.xml", SpringJpaTestingClass.class); Customer customer = new Customer(); customer.setId(“123”); customer.setFirstName(“john”); customer.setLastName(“smith”); CustomerRepository customerRepository = (CustomerRepository)ac.getBean(“customerRepository”); System.out.println("Inserting Customer"); customerRepository.insertCustomer(customer); System.out.println("Listing all Customer’s"); List allCustomers = customerRepository.getAllCustomers(); for (Customer aCustomer : allCustomers) { System.out.println(aCustomer); } System.out.println("Selecting a Customer by Id '123'"); Customer createdCustomer = customerRepository.getCustomer(“123”); System.out.println(createdCustomer); } } |
Summary
In this chapter I have explained in detail on the various data access technology support which the Spring framework provides you to utilize it effectively in your application. Using it enables you to have layered architecture principles in your application. If your design is good enough, the higher layer will never know the data management technologies used beneath and using Spring IoC, it can be swapped very easily down the layer according to your application requirement.
Spring also gives very good way of isolating various exceptions that the various data access technology throws into some meaningful exceptions using the DataAccessException hierarchy in a consistent and elegant way.
I the later sections of the chapter I consciously took time to explain in some detail the various important technologies prominent in the present application development scenario.
Page Visitors: 10629
Tomcy John
Latest posts by Tomcy John (see all)
- A Guide to Continuous Improvement for Architects - February 2, 2023
- Cloud-first Architecture Strategy - January 26, 2023
- Architecture Strategy and how to create One - January 24, 2023
Hi my friend! I wish to say that this article is awesome, nice written and come with approximately all important infos. Iˇ¦d like to peer more posts like this .
simple, well written. keep writing..