zoukankan      html  css  js  c++  java
  • 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;
    
    @Repository
    public 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;
    
    @Service
    public 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());
        }
    }
  • 相关阅读:
    Vim 配置 winmanager
    删除字符串中重复字符
    检查字符串中是否存在重复字符
    字符串逆序输出
    shell 循环使用
    Windows下JNI执行步骤
    JNI中使用cl命令生成DLL文件
    javaZIP压缩文件
    java Mail发送邮件
    关于在同一个DIV下的Hover效果问题
  • 原文地址:https://www.cnblogs.com/shi-blog/p/4132829.html
Copyright © 2011-2022 走看看