Spring with Hibernate persistence and transactions example

来源:互联网 发布:mac vm共享的文件在哪 编辑:程序博客网 时间:2024/06/06 00:18

In this tutorial you will learn how to implement Hibernate persistence using the Spring framework in a transactional fashion.

Introduction

After reading this tutorial you will be able to implement Hibernate persistence using Spring framework. Additionally you will also use Spring Hibernate transaction manager to manage all the transactional boilerplate code and wiring for you.

This tutorial considers the following software and environment:

  • Ubuntu 12.04
  • Maven 3.0.4
  • JDK 1.7.0.09
  • Spring 3.2.0
  • Hibernate 4.1.9
  • MySQL 5.5.28

Configuration

Configure Maven to get the required Spring dependencies:

Maven pom.xml file referencing required dependencies

<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.byteslounge.spring.tx</groupId>  <artifactId>com-byteslounge-spring-tx</artifactId>  <version>1.0-SNAPSHOT</version>  <packaging>jar</packaging>  <name>com-byteslounge-spring-tx</name>  <url>http://maven.apache.org</url>  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    <!-- Define Spring version as a constant -->    <spring.version>3.2.0.RELEASE</spring.version>  </properties>  <dependencies>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-core</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-context</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-tx</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>       <groupId>org.springframework</groupId>       <artifactId>spring-orm</artifactId>       <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>commons-dbcp</groupId>      <artifactId>commons-dbcp</artifactId>      <version>1.2.2</version>    </dependency>    <dependency>        <groupId>javax.persistence</groupId>        <artifactId>persistence-api</artifactId>        <version>1.0</version>    </dependency>    <dependency>       <groupId>org.hibernate</groupId>       <artifactId>hibernate-core</artifactId>       <version>4.1.9.Final</version>    </dependency>  </dependencies></project>

Now place yourself in the project directory and issue the following command to prepare your project for Eclipse:

mvn eclipse:eclipse

After conclusion you can import the project into Eclipse.
This tutorial will not focus on how to configure a MySQL instance or database but will consider the following table:

MySQL table used in this exampleCREATE TABLE USER (  ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,  USERNAME VARCHAR (32) NOT NULL,  NAME VARCHAR (64) NOT NULL,  UNIQUE (USERNAME));

Entity and DAO

We will need a simple Java class to represent USER table information in the form of a JPA Entity. This class will be the model for this example.

User.java class

package com.byteslounge.spring.tx.model;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name="USER")public class User {  @Id  @GeneratedValue(strategy = GenerationType.AUTO)  @Column(name="ID", nullable = false)  private int id;  @Column(name="USERNAME", nullable = false)  private String username;  @Column(name="NAME", nullable = false)  private String name;  public int getId() {    return id;  }  public void setId(int id) {    this.id = id;  }  public String getUsername() {    return username;  }  public void setUsername(String username) {    this.username = username;  }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }}

Basically we are defining our model object and the mappings of the User object to the USER table. If you are familiar with JPA this will be straight forward.

Now we define our DAO interface and implementation:

DAO interface

package com.byteslounge.spring.tx.dao;import java.util.List;import com.byteslounge.spring.tx.model.User;public interface UserDAO {  void insertUser(User user);  User getUserById(int userId);  User getUser(String username);  List<User> getUsers();}

DAO implementation

package com.byteslounge.spring.tx.dao.impl;import java.util.List;import org.hibernate.Criteria;import org.hibernate.Query;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.byteslounge.spring.tx.dao.UserDAO;import com.byteslounge.spring.tx.model.User;@Servicepublic class UserDAOImpl implements UserDAO {  @Autowired  private SessionFactory sessionFactory;  @Override  public void insertUser(User user) {    sessionFactory.getCurrentSession().save(user);  }  @Override  public User getUserById(int userId) {    return (User) sessionFactory.      getCurrentSession().      get(User.class, userId);  }  @Override  public User getUser(String username) {    Query query = sessionFactory.      getCurrentSession().      createQuery("from User where username = :username");    query.setParameter("username", username);    return (User) query.list().get(0);  }  @Override  @SuppressWarnings("unchecked")  public List<User> getUsers() {    Criteria criteria = sessionFactory.      getCurrentSession().      createCriteria(User.class);    return criteria.list();  }}

We are basically defining some operations that will be executed over the USER table. Insert a new user, get a user by ID (Primary Key), get a user by it’s username and fetching all users.

We use the @Autowired in the SessionFactory property so it gets injected by the Spring container during bean initialization. We will see later how we configure our Hibernate session factory.

The Service bean

Now we need to define the actual service bean that will make use of the DAO we previously defined. You usually implement your business logic in this layer: The service layer. Since this is a very simple example the service layer will just make use of the DAO to interact with the Database and return the results directly to the caller.

Service interface

package com.byteslounge.spring.tx.user;import java.util.List;import com.byteslounge.spring.tx.model.User;public interface UserManager {  void insertUser(User user);  User getUserById(int userId);  User getUser(String username);  List<User> getUsers();}

Service implementation

package com.byteslounge.spring.tx.user.impl;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import com.byteslounge.spring.tx.dao.UserDAO;import com.byteslounge.spring.tx.model.User;import com.byteslounge.spring.tx.user.UserManager;@Servicepublic class UserManagerImpl implements UserManager {  @Autowired  private UserDAO userDAO;  @Override  @Transactional  public void insertUser(User user) {    userDAO.insertUser(user);  }  @Override  @Transactional  public User getUserById(int userId) {    return userDAO.getUserById(userId);  }  @Override  @Transactional  public User getUser(String username) {    return userDAO.getUser(username);  }  @Override  @Transactional  public List<User> getUsers() {    return userDAO.getUsers();  }}

As we have already stated before it should be in this service layer that the business logic would be implemented. In this simple example we are just using the DAO to interact with the Database and return the results to the caller.

Things to note in this class: The service implementation is annotated with @Service which means that this will be a bean managed by Spring. UserDAO is annotated with @Autowired so it will be injected by the Spring container.

Methods are annotated with @Transactional so the Spring Hibernate transaction manager creates the required transactions and the respective sessions.

Spring configuration file

Now we define the configuration file used for this example:

Spring XML configuration file

<?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:context="http://www.springframework.org/schema/context"  xmlns:tx="http://www.springframework.org/schema/tx"  xmlns:p="http://www.springframework.org/schema/p"  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.xsd">  <tx:annotation-driven />  <context:component-scan     base-package="com.byteslounge.spring.tx.dao.impl" />  <context:component-scan     base-package="com.byteslounge.spring.tx.user.impl" />  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"    destroy-method="close">    <property name="driverClassName" value="com.mysql.jdbc.Driver" />    <property name="url" value="jdbc:mysql://localhost:3306/TEST" />    <property name="username" value="testuser" />    <property name="password" value="testpasswd" />  </bean>  <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">    <property name="dataSource" ref="dataSource"></property>    <property name="hibernateProperties">      <props>        <prop          key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>        <prop key="hibernate.show_sql">true</prop>      </props>    </property>    <property name="packagesToScan" value="com.byteslounge.spring.tx.model" />  </bean>  <bean id="transactionManager"    class="org.springframework.orm.hibernate4.HibernateTransactionManager"     p:sessionFactory-ref="sessionFactory">  </bean></beans>

Important things to note in the configuration file: We define a datasource bean pointing to our MySQL instance. The sessionFactory bean represents the Hibernate session factory that will create sessions to interact with the database.

We needed to define the packages where the container should look for Entities. In our case it will look for entities in com.byteslounge.spring.tx.model. We also defined the datasource that the session factory will use (property dataSource).

There is also a transactionManager bean. This bean is the Spring Hibernate transaction manager that will handle transaction related boilerplate code and wiring for us. We needed to define the session factory that the transaction manager will use to create sessions (attribute sessionFactory-ref).

tx:annotation-driven element defines that we are declaring transactions using annotations in our classes (remember @Transactional annotations in our service layer?). Finally we define the packages where Spring should look for beans using context:component-scan elements.

Note: In this example we used MySQL as the data repository so we need to specify the correct MySQL Driver in the dataSource bean. This Driver must be in the application classpath when you run your application. Drivers can be usually found in the respective vendor websites. In our case we got it from MySQL website.

Testing the application

Let’s create a simple class to test our example:

Simple Main testing class

package com.byteslounge.spring.tx;import java.util.List;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.byteslounge.spring.tx.model.User;import com.byteslounge.spring.tx.user.UserManager;public class Main {    public static void main( String[] args )    {      ApplicationContext ctx =         new ClassPathXmlApplicationContext("spring.xml");      UserManager userManager =         (UserManager) ctx.getBean("userManagerImpl");      User user = new User();      user.setUsername("johndoe");      user.setName("John Doe");      userManager.insertUser(user);      System.out.println("User inserted!");      user = userManager.getUser("johndoe");      System.out.println("\nUser fetched by username!"        + "\nId: " + user.getId()        + "\nUsername: " + user.getUsername()        + "\nName: " + user.getName());      user = userManager.getUserById(user.getId());      System.out.println("\nUser fetched by ID!"        + "\nId: " + user.getId()        + "\nUsername: " + user.getUsername()        + "\nName: " + user.getName());      List<User> users = userManager.getUsers();      System.out.println("\nUser list fetched!"          + "\nUser count: " + users.size());    }}

When we run our test the following output will be generated:

User inserted! User fetched by username! Id: 1 Username: johndoe Name: John Doe User fetched by ID! Id: 1 Username: johndoe Name: John Doe User list fetched! User count: 1

You have successfully integrated Hibernate with Spring. To be more precise you used Spring Hibernate transaction manager to manage your Hibernate sessions and transactions.

0 0
原创粉丝点击