Spring4-4-整合Hibernate

一.整合目标

(1)又IOC容器来管理Hibernate的SessionFactory
(2)让Hibernate使用上Spring的生命式事务

二.整合步骤

1.加入hibernate
(1)加入jar包


Paste_Image.png

(2)新建hibernate配置文件hibernate.cfg.xml

    <session-factory>
        <!-- 配置hibernate基本属性 -->
        <!-- 1.数据源配置到IOC容器中,所以在此不需要配置数据连接相关信息 -->
        <!-- 2.关联hbm.xml也在IOC容器配置SessionFactory实例时在进行配置 -->
        
        <!-- 3.配置hibernate的基本属性:方言,SQL显示及格式,生成数据表的策略以及二级缓存 -->
        <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>

(3)编写持久化类以及对应的.hbm.xml映射文件

Paste_Image.png

2.加入Spring
(1)加入jar包
Paste_Image.png

(2)配置Spring配置文件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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    <!-- Spring与Hibernate整合 -->
    
    <context:component-scan base-package="lxf.spring.hibernate"></context:component-scan>
    <!-- 配置数据源 -->
     <!-- 导入属性文件 classpath代表类路径 -->
    <context:property-placeholder location="classpath:db.properties"/> 
    <!--  配置c3p0数据源 -->
    <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实例 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
             <!-- 配置数据源属性 -->
            <property name="dataSource" ref="dataSource"></property>
            <!-- 配置Hibernate 配置文件的位置及名称
            <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>-->
            <!-- hibernate配置文件的内容也可以作为Spring的属性配置 -->
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                    <prop key="hibernate.show_sql">true</prop>
                    <prop key="hibernate.format_sql">true</prop>
                    <prop key="hibernate.hbm2ddl.auto">true</prop>
                </props>
            </property>
            <!-- 配置 Hibernate映射文件的位置以及名称,可以使用通配符-->
            <property name="mappingLocations" value="classpath:lxf/spring/hibernate/entiries/*.hbm.xml"></property>
    </bean>
    
    <!-- 配置Spring的声明式事务 -->
    <!-- 1.配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    <!-- 2.配置事务属性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="get*" read-only="true"/>
                <tx:method name="*" />
            </tx:attributes>
    </tx:advice>
    <!-- 3.配置事务切点,并把切点和事务属性关联 -->
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut expression="execution( * lxf.spring.hibernate.service.impl.*.*(..))" id="txPointCut"/>
        <!-- 将切入点和属性关联 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
</beans>

(3)单元测试SpringHibernateTest.java

/**
 * 单元测试Spring整合hibernate类
 * @author lxf
 */
public class SpringHibernateTest {
    private ApplicationContext ctx = null;
    {
        ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
    /**
     * 测试数据源连接
     * @throws SQLException 
     */
    @Test
    public void testDataSource() throws SQLException {
        DataSource dataSource = (DataSource)ctx.getBean("dataSource");
        System.out.println(dataSource.getConnection());     
    }
}

如果配置没有问题,单元测试会成功,而且会自动在数据库中建立那两张表

三.Spring hibernate事务流程

 * 1.在方法开始之前
 * (1)获取Session
 * (2)把Session和当前线程绑定,这样就可以在Dao中使用
 *              SessionFactory的getCurrentSession方法获取Session了
 * (3)开启事务
 * 
 * 2.若方法正常结束,则没有出现异常,则
 * (1)提交事务
 * (2)使和当前线程的Session解除绑定
 * (3)关闭Session
 * 
 * 3.若方法出现异常,则:
 * (1)回滚事务
 * (2)使和当前线程的Session解除绑定
 * (3)关闭Session

Spring Hibernate事务实现除了BookShopDaoImpl.java与其他文件不一样,其他都一样:

package lxf.spring.hibernate.dao.impl;

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 lxf.spring.hibernate.dao.BookShopDao;
import lxf.spring.hibernate.exception.BookStockException;
import lxf.spring.hibernate.exception.UserAcountException;

@Repository("bookShopDao")
public class BookShopDaoImpl implements BookShopDao {
      
    @Autowired
    private SessionFactory sessionFactory;
    
    //获得和当前线程绑定的session
    public Session getSession()
    {
       return sessionFactory.getCurrentSession();
    }

    @Override
    public double findBookPriceBookId(Integer bookId) {
        String hql ="SELECT b.price FROM Books b WHERE b.book_id = ?";
        Query query = getSession().createQuery(hql).setInteger(0, bookId);
        return (double)query.uniqueResult();
    }

    @Override
    public void updateBookStock(Integer bookId) {
           //先查询是否有库存
            String hql ="SELECT b.stock  FROM Books b WHERE b.book_id= ?";
            Query query = getSession().createQuery(hql).setInteger(0, bookId);
            int stock = (int)query.uniqueResult();
            if(stock <= 0)
            {
                throw new BookStockException("图书库存不足!");
            }
            //修改库存
            String hql2 = "UPDATE Books b SET b.stock =b. stock-1 WHERE b.book_id = ?";
            getSession().createQuery(hql2).setInteger(0, bookId).executeUpdate();           
    }

    @Override
    public void updateUserAccount(Integer userId, double price) {
        //先查询账户余额是否够
        String hql ="SELECT a.balance  FROM Acount a WHERE a.id = ?";
        Query query = getSession().createQuery(hql).setInteger(0, userId);
        double balance = (double)query.uniqueResult();
        if(balance <= 0)
        {
            throw new UserAcountException("用户账户余额不足!");
        }
        //修改账户余额
        String hql2 = "UPDATE Acount a SET a.balance = a.balance-? WHERE a.id = ?";
        getSession().createQuery(hql2).setDouble(0, price).setInteger(1, userId).executeUpdate();        
    }
}

代码演示点击

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容