Spring4整合Hibernate4详细示例
来源:互联网 发布:网上免费打电话软件 编辑:程序博客网 时间:2024/06/07 05:59
原文:http://blog.csdn.net/kris234seth/article/details/49872867
1. Spring整合Hibernate,主要是解决什么问题?
a、让Spring提供的IOC容器来管理Hibernate的SessionFactory
b、让Hibernate使用Spring提供的声明式事物
2. 整合步骤:
新建一个Java工程,并新建用来保存依赖jar包的lib目录
①. 加入Hibernate支持:
1. 加入Hibernate的required的jar包:
antlr-2.7.7.jar
dom4j-1.6.1.jar
hibernate-commons-annotations-4.0.2.Final.jar
hibernate-core-4.2.5.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.15.0-GA.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
2.加入MySQL与C3p0连接池支持:
c3p0-0.9.2.1.jar
mchange-commons-java-0.2.3.4.jar
mysql-connector-java-5.1.7-bin.jar
注意:jar包加入之后,需要全部选中,右键-》BuildPath,将其导入
3.添加Hibernate的配置文件(hibernate.cfg.xml):
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
-
-
-
-
- <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
-
- <property name="hibernate.show_sql">true</property>
- <property name="hibernate.format_sql">true</property>
-
- <property name="hibernate.hbm2ddl.auto">update</property>
-
- </session-factory>
- </hibernate-configuration>
4. 创建测试使用的持久化类以及生成Hibernate的映射文件
本例所用到的持久化类以其映射文件如下:
- public class Book {
-
- private int id;
- private String bookName;
- private String isbn;
- private float price;
- private int stock;
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getBookName() {
- return bookName;
- }
-
- public void setBookName(String bookName) {
- this.bookName = bookName;
- }
-
- public String getIsbn() {
- return isbn;
- }
-
- public void setIsbn(String isbn) {
- this.isbn = isbn;
- }
-
- public float getPrice() {
- return price;
- }
-
- public void setPrice(float price) {
- this.price = price;
- }
-
- public int getStock() {
- return stock;
- }
-
- public void setStock(int stock) {
- this.stock = stock;
- }
-
- }
- public class Account {
-
- private int id;
- private String username;
- private float balance;
-
- 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 float getBalance() {
- return balance;
- }
-
- public void setBalance(float balance) {
- this.balance = balance;
- }
-
- }
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
-
- <hibernate-mapping>
- <class name="com.elgin.spring.hibernate.entity.Book" table="SH_BOOK">
- <id name="id" type="int">
- <column name="ID" />
- <generator class="native" />
- </id>
-
- <property name="bookName" type="java.lang.String">
- <column name="BOOKNAME" />
- </property>
-
- <property name="isbn" type="java.lang.String">
- <column name="ISBN" />
- </property>
-
- <property name="price" type="float">
- <column name="PRICE" />
- </property>
-
- <property name="stock" type="int">
- <column name="STOCK" />
- </property>
-
- </class>
- </hibernate-mapping>
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
-
- <hibernate-mapping>
- <class name="com.elgin.spring.hibernate.entity.Account" table="SH_ACCOUNT">
- <id name="id" type="int">
- <column name="ID" />
- <generator class="native" />
- </id>
-
- <property name="username" type="java.lang.String">
- <column name="USERNAME" />
- </property>
-
- <property name="balance" type="float">
- <column name="BALANCE" />
- </property>
-
- </class>
- </hibernate-mapping>
②. 加入Spring支持:
1. 加入Spring的required的jar包:
com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar commons-logging-1.1.3.jar spring-aop-4.1.0.RELEASE.jar spring-aspects-4.1.0.RELEASE.jar spring-beans-4.1.0.RELEASE.jar spring-context-4.1.0.RELEASE.jar spring-core-4.1.0.RELEASE.jar spring-expression-4.1.0.RELEASE.jar spring-jdbc-4.1.0.RELEASE.jar spring-orm-4.1.0.RELEASE.jar spring-test-4.1.0.RELEASE.jar spring-tx-4.1.0.RELEASE.jar spring-web-4.1.0.RELEASE.jar spring-webmvc-4.1.0.RELEASE.jar 同样需要BuildPath!
2.加入Spring的配置文件:applicationContext.xml
applicationContext.xml 配置内容:
- <?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:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
- 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-4.1.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
-
-
- <context:component-scan base-package="com.elgin.spring.hibernate"></context:component-scan>
-
-
-
-
- <context:property-placeholder location="classpath:db.properties"/>
-
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="user" value="${jdbc.user}"></property>
- <property name="password" value="${jdbc.password}"></property>
- <property name="driverClass" value="${jdbc.driverClass}"></property>
- <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
-
- <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
- <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
- </bean>
-
-
- <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
-
- <property name="dataSource" ref="dataSource"></property>
-
- <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
-
- <property name="mappingLocations" value="classpath:com/elgin/spring/hibernate/entity/*.hbm.xml"></property>
- </bean>
-
-
- <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
- <property name="sessionFactory" ref="sessionFactory"></property>
- </bean>
-
-
- <tx:advice id="txAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <tx:method name="get*" read-only="true"/>
- <tx:method name="purchase" propagation="REQUIRES_NEW"/>
- <tx:method name="*"/>
- </tx:attributes>
- </tx:advice>
-
-
- <aop:config>
- <aop:pointcut expression="execution(* com.elgin.spring.hibernate.service.*.*(..))" id="txPointcut"/>
- <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
- </aop:config>
-
- </beans>
依赖的数据库配置文件db.properties:- jdbc.user=root
- jdbc.password=root123
- jdbc.driverClass=com.mysql.jdbc.Driver
- jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring_hibernate
- jdbc.initPoolSize=5
- jdbc.maxPoolSize=10
至此,Spring的配置、Hibernate的配置、以及二者整合的相关配置都配置完毕。下面通过代码测试。3.整合测试:
工程目录:
新建上述各个目录:
1. 在dao下面新建接口:
- public interface BookShopDao {
-
-
-
-
-
-
- public float findPriceByIsbn(String isbn);
-
-
-
-
-
-
- public void updateBookStock(String isbn,int n);
-
-
-
-
-
-
-
-
- public void updateAccount(String username,float price,int n);
- }
对应的在impl下完成上述接口的实现类(注解@Repository,用来标注持久层,同时表示此组件交给spring的IOC容器管理)在使用spring的相关注解时,需要在spring的配置文件中开启注解自动扫描:
-
- <context:component-scan base-package="com.elgin.spring.hibernate"/>
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Repository;
-
- import com.elgin.spring.hibernate.dao.BookShopDao;
- import com.elgin.spring.hibernate.exception.BalanceNotEnough;
- import com.elgin.spring.hibernate.exception.BookStockNotEnoughException;
-
- @Repository
- public class BookShopDaoImpl implements BookShopDao {
-
- @Autowired
- private SessionFactory sessionfactory;
-
-
-
-
-
- private Session getSession(){
- return sessionfactory.getCurrentSession();
- }
-
- @Override
- public float findPriceByIsbn(String isbn) {
- String hql="select b.price from Book b where b.isbn=?";
- float price=(float) getSession().createQuery(hql).setString(0, isbn).uniqueResult();
- return price;
- }
-
- @Override
- public void updateBookStock(String isbn, int n) {
-
- String hq="Select b.stock from Book b where b.isbn=?";
- int stock=(int) getSession().createQuery(hq).setString(0, isbn).uniqueResult();
- if(stock < n){
- throw new BookStockNotEnoughException("库存不足");
- }
- String hql="update Book b set b.stock=b.stock-? where b.isbn=?";
- Query query=getSession().createQuery(hql).setInteger(0, n).setString(1, isbn);
- query.executeUpdate();
- }
-
- @Override
- public void updateAccount(String username, float price, int n) {
-
- String hql="select a.balance from Account a where a.username=?";
- float balance=(float) getSession().createQuery(hql).setString(0, username).uniqueResult();
- if(balance < n*price){
- throw new BalanceNotEnough("余额不足");
- }
- String hql1="update Account a set a.balance=a.balance-? where a.username=?";
- getSession().createQuery(hql1).setFloat(0, n*price).setString(1, username).executeUpdate();
- }
-
- }
实现类中用到的2个异常类:- public class BalanceNotEnough extends RuntimeException {
-
-
-
-
- private static final long serialVersionUID = 1L;
-
- public BalanceNotEnough(String msg) {
- super(msg);
- }
-
- }
- public class BookStockNotEnoughException extends RuntimeException {
-
-
-
-
- private static final long serialVersionUID = 1L;
-
- public BookStockNotEnoughException(String msg) {
- super(msg);
- }
- }
在service包下新建下面的接口:- public interface BookShopService {
-
-
-
-
-
-
- public void purchase(String username,String isbn,int n);
- }
在service.impl下完成它的实现类(@Service 用来标注service层,表示此组件为service并交给Spring的IOC容器管理;@Autowired 自动注入 ,表示此对象由IOC容器负责初始化并注入):- @Service
- public class BookShopSeviceImpl implements BookShopService {
-
- @Autowired
- private BookShopDao bookShopDao;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- @Override
- public void purchase(String username, String isbn, int n) {
- float price=bookShopDao.findPriceByIsbn(isbn);
- bookShopDao.updateBookStock(isbn, n);
- bookShopDao.updateAccount(username, price, n);
- }
-
- }
编写单元测试类:若想使用如下配置进行单元测试,必须要加入spring单元测试的jar包:spring-test-4.1.0.RELEASE.jar
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration("classpath:applicationContext.xml")
- public class SpringHibernateTest {
-
-
- @Autowired
- private BookShopService bookShopService;
-
- @Test
- public void testPurchaseBook(){
- bookShopService.purchase("aaa", "java-1122", 2);
- }
-
- }
首先,注释掉测试方法中额外的代码,启动单元测试,让Hibernate生成用到的数据表:SH_BOOK 与SH_ACCOUNT让后在2个表中各加入测试所需要的数据如下图:
运行上述单元测试方法,执行成功,查看数据库,book的库存STOCK变为43,account中的账户余额变为130.
再次运行,程序抛出异常:
com.elgin.spring.hibernate.exception.BalanceNotEnough: 余额不足
查看数据库发现:
book的库存STOCK仍旧为43,account中的账户余额仍旧为130.
这就是spring的事物的作用,程序出现异常,回滚事务,关闭session。
本次整合测试代码:
本次整合测试代码