首页 > 代码库 > Spring整合Hibernate

Spring整合Hibernate

  • 整合什么?

    1. 让Spring的IOC容器生成Hibernate的SessionFactory。

    2. 让Hibernate使用上Spring的事务声明。

  • 整合步骤

    1. 加入Hibernate。

              (1) 导入Hibernate开发包。

              (2) 编写Hibernate配置文件:hibernate.cfg.xml。我们在文件只需要配置方言、SQL显示及其格式化、生成数据库表的策略以及二级缓存的

         的相关信息。对于数据源信息我们配置到Spring的配置文件中,让Spring的IOC容器来管理数据源,关联的映射文件.hbm.xml也配置在Spring

         的配置文件中。

         2. 加入Spring

               (1) 导入开发包。

               (2) 编写Spring的配置文件。配置数据源、配置Hibernate的SessionFactory、配置Spring的事务声明。

  • 代码展示

模拟情景:用户去买书(规定每次只能买一本书),用户的账户余额会减少,同时书本的库存也会减少。

1. 实体类

package hibernate.entity;/** * 账户 * @author SHI */public class Account {    private Integer id;    private String username;// 账户名称    private int balance;//账户余额    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public int getBalance() {        return balance;    }    public void setBalance(int balance) {        this.balance = balance;    }    @Override    public String toString() {        return "Account [id=" + id + ", username=" + username + ", balance="                + balance + "]";    }}

 

package hibernate.entity;/** * 书本 * @author SHI */public class Book {    private Integer id;    private String bookName;//书本名称    private String bookId;//书本编号    private int price;//书本价格    private int stock;//书本库存    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getBookName() {        return bookName;    }    public void setBookName(String bookName) {        this.bookName = bookName;    }    public String getBookId() {        return bookId;    }    public void setBookId(String bookId) {        this.bookId = bookId;    }    public int getPrice() {        return price;    }    public void setPrice(int price) {        this.price = price;    }    public int getStock() {        return stock;    }    public void setStock(int stock) {        this.stock = stock;    }    @Override    public String toString() {        return "Book [id=" + id + ", bookName=" + bookName + ", bookId=" + bookId                + ", price=" + price + ", stock=" + stock + "]";    }}

2. DAO层代码

package hibernate.dao;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;@Repositorypublic class BookDao {        @Autowired    private SessionFactory sessionFactory;    /*     * 不推荐使用 HibernateTemplate 和 HibernateDaoSupport,因为     * 这样会导致DAO和Spring API进行耦合,可移植性差。     * private HibernateTemplate hibernateTemplate;     * private HibernateDaoSupport daoSupport;     */        //获取和当前线程绑定的Session    public Session getSession() {        return sessionFactory.getCurrentSession();    }            /**     * 根据书本编号查询书本的价格     * @param bookId     * @return     */    public double bookPriceById(String bookId) {        String hql = "select b.price from Book b where b.bookId = ?";        Query query = this.getSession().createQuery(hql).setString(0, bookId);        return (Integer) query.uniqueResult();    }    /**     * 根据书本编号更新书本的库存数量     * @param bookId     */    public void updateBookStock(String bookId)  {        //1.检查库存数量        String _hql = "select b.stock from Book b where b.bookId = ?";        int result = (Integer) getSession().createQuery(_hql).setString(0, bookId).uniqueResult();        if(result <= 0) {            throw new RuntimeException("库存不足...");        }        String hql = "update Book b set b.stock = b.stock - 1 where b.bookId = ?";        Query query = getSession().createQuery(hql).setString(0, bookId);        query.executeUpdate();    }    /**     * 更新账户余额     * @param username     * @param price     */    public void updateUserAccount(String username, double price)  {        //1.检查账户余额        String _hql = "select a.balance from Account a where a.username = ?";        int balance = (Integer) getSession().createQuery(_hql).setString(0, username).uniqueResult();        if(balance <= price) {            throw new RuntimeException("余额不足...");        }        String hql = "update Account a set a.balance = a.balance - ? where a.username = ?";        this.getSession().createQuery(hql).setDouble(0, price).setString(1, username).executeUpdate();    }}

 

3. 业务层代码

package hibernate.service;import hibernate.dao.BookDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class BookService {    @Autowired    private BookDao bookDao;        /**     * Spring整合Hibernate 事务的流程     * 1. 在方法开始之前     * ①. 获取 Session     * ②. 把 Session 和当前线程绑定, 这样就可以在 Dao 中使用 SessionFactory 的     * getCurrentSession() 方法来获取 Session 了     * ③. 开启事务     *      * 2. 若方法正常结束, 即没有出现异常, 则     * ①. 提交事务     * ②. 使和当前线程绑定的 Session 解除绑定     * ③. 关闭 Session     *      * 3. 若方法出现异常, 则:     * ①. 回滚事务     * ②. 使和当前线程绑定的 Session 解除绑定     * ③. 关闭 Session     */    public void buyBook(String username,String bookId)  {        //1.获取单价        double price = bookDao.bookPriceById(bookId);        //2.更新库存        bookDao.updateBookStock(bookId);        //3.更新余额        bookDao.updateUserAccount(username, price);    }}

 

4. 配置文件

    (1) Hibernate的配置文件

<!DOCTYPE hibernate-configuration PUBLIC    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration>    <session-factory>        <property name="show_sql">true</property>        <property name="format_sql">true</property>        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>        <property name="hbm2ddl.auto">update</property>    </session-factory></hibernate-configuration>

 

    (2) Spring配置文件

<?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/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.0.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">        <context:component-scan base-package="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>        <!-- 配置Hibernate的SessionFactory实例:通过Spring提供的LocalSessionFactoryBean -->    <bean id="sessionFactory"         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">        <!-- 配置数据源属性 -->        <property name="dataSource" ref="dataSource"></property>                <!-- 配置hibernate文件 -->        <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>                <!-- 配置hibernate映射文件,可使用通配符 -->        <property name="mappingLocations" value="classpath:hibernate/hbm/*.hbm.xml"></property>    </bean>        <!-- 配置Spring事务管理    1.配置事务管理器 -->    <bean id="transactionManager"         class="org.springframework.orm.hibernate4.HibernateTransactionManager">        <property name="sessionFactory" ref="sessionFactory"></property>    </bean>    <!-- 2.配置事务属性 -->    <tx:advice id="txAdvice" transaction-manager="transactionManager">        <tx:attributes>            <tx:method name="buyBook"/>        </tx:attributes>    </tx:advice>        <!-- 3.配置事务切入点,以及把事务切入点和事务属性关联 -->    <aop:config>        <aop:pointcut expression="execution(* hibernate.service.*.*(..))" id="pointcut"/>        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>    </aop:config></beans>

 

5. 测试代码。测试的时候可以手动的更改数据可表中的数据,让程序抛出异常,测试事务的使用。

 

package hibernate;import hibernate.service.BookService;import java.sql.SQLException;import javax.sql.DataSource;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringHibernateTest {    private ApplicationContext ac;    private BookService bookService;         {        ac = new ClassPathXmlApplicationContext("bean.xml");        bookService = ac.getBean(BookService.class);    }        @Test    public void testBuyBook() {        bookService.buyBook("Kate", "1");    }        @Test    public void getDataSource() throws SQLException {        DataSource dataSource = (DataSource) ac.getBean("dataSource");        System.out.println(dataSource.getConnection());    }}

Spring整合Hibernate