spring整合hibernate

spring整合hibernate_第1张图片

1.Spring整合Hibernate整合什么?

①由IOC容器来管理Hibernate的SessionFactory

②让Hibernate使用Spring的声明式事物


2.整合步骤

①加入Hibernate

Jar包

添加Hibernate配置文件hibernate.cfg.xml

编写Hibernate持久化类对应的.hbm.xml文件

②加入Spring

jar包

加入Spring的配置文件

③整合


BookShopDao.java接口

1
2
3
4
5
6
7
8
public  interface  BookShopDao {
     //根据书号获取书的单价
     public  int  findBookPriceByIsbn(String isbn);
     //更新书的库存,使书号对应的库存-1
     public  void  updateBookStock(String isbn);
     //更新用户的账户余额,是username的balance-price
     public  void  updateUserAccount(String username,  int  price);
}

BookShopDao.java接口的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Repository
public  class  BookShopDaoImpl  implements  BookShopDao{
 
     @Autowired
     private  SessionFactory sessionFactory;
     
     /**HibernateTemplate和HibernateDaoSupport是Spring API,不建议使用。
      * 这样会导致Dao和Spring API的耦合。可移植性变差。
     *private HibernateTemplate hibernateTemplate;
     */
     
     private  Session getSession(){
         //获取和当前线程绑定的session
         return  sessionFactory.getCurrentSession();
     }
     
     @Override
     public  int  findBookPriceByIsbn(String isbn) {
         String hql =  "select b.price from Book b where b.isbn = ?" ;
         Query query = getSession().createQuery(hql).setString( 0 , isbn);
         return  (Integer) query.uniqueResult();
     }
 
     @Override
     public  void  updateBookStock(String isbn) {
         //验证书的库存是否充足
         String hql =  "select b.stock from Book b where b.isbn = ?" ;
         int  stock = (Integer) getSession().createQuery(hql).setString( 0 , isbn).uniqueResult();
         if  (stock <=  0 ) {
             throw  new  BookStockException( "库存不足" );
         }
         hql =  "update Book b set b.stock = b.stock - 1 where b.isbn = ?" ;
         getSession().createQuery(hql).setString( 0 , isbn).executeUpdate();
     }
 
     @Override
     public  void  updateUserAccount(String username,  int  price) {
         //验证余额是否足够
         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  UserAccountException( "余额不足" );
         }
         hql =  "update Account a set a.balance = a.balance - ? where a.username = ?" ;
         getSession().createQuery(hql).setInteger( 0 , price).setString( 1 , username).executeUpdate();
     }
 
}

BookShopService.java接口

1
2
3
4
public  interface  BookShopService {
 
     public  void  purchase(String username, String isbn);
}

BookShopService.java接口的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Service
public  class  BookShopServiceImpl  implements  BookShopService{
 
     @Autowired
     private  BookShopDao bookShopDao;
     
     /**
      * Spring Hibernate 事务流程
      * 1.在方法开始之前
      * ①获取Session
      * ②把Session和当前线程绑定,这样就可以在Dao中使用SessionFactory的getCurrentSession()来获取Session了
      * ③开启事务
      * 2.若方法正常结束,即没有出现异常,则
      * ①提交事务
      * ②使和当前线程绑定的Session解除绑定
      * ③关闭Session
      * 3.若方法抛出异常,则
      * ①回滚事务
      * ②使和当前线程绑定的Session解除绑定
      * ③关闭Session
      */
     @Override
     public  void  purchase(String username, String isbn) {
         
         /*
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         */
         //获取书的单价
         int  price = bookShopDao.findBookPriceByIsbn(isbn);
         //更新书的库存
         bookShopDao.updateBookStock(isbn);
         //更新用户余额
         bookShopDao.updateUserAccount(username, price);
     }
 
}

Cashier接口

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public  class  CashierImpl  implements  Cashier{
 
     @Autowired
     private  BookShopService bookShopService;
     @Override
     public  void  checkout(String username, List<String> isbns) {
         for  (String isbn:isbns){
             bookShopService.purchase(username, isbn);
         }
     }
 
}


实体类Account.java  (省略hbm.xml配置文件)

1
2
3
4
5
6
public  class  Account {
     private  Integer id;
     private  String username;
     private  int  balance;
     //..
}


实体类Book.java  (省略hbm.xml配置文件)

1
2
3
4
5
6
7
8
9
public  class  Book {
 
     private  Integer id;
     private  String bookName;
     private  String isbn;
     private  int  price;
     private  int  stock;
     //...
}


db.properties

1
2
3
4
5
6
7
jdbc.user=root
jdbc.password=123456
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql: ///SpringHibernate ?createDatabaseIfNotExist\= true
 
jdbc.initialPoolSize=5
jdbc.maxPoolSize=10


hibernate.cfg.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<? 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 >
     <!-- 配置Hibernate的基本属性 -->
     <!-- 1.数据源需配置到IOC容器中,所以在此处不再需要配置数据源 -->
     <!-- 2.关联.hbm.xml文件也在IOC容器配置SessionFactory实例时进行配置 -->
     <!-- 3.配置Hibernate的基本属性:方言、SQL显示、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 >
     
     <!-- 配置Hibernate二级缓存相关的属性...暂略 -->
     </ session-factory >
</ hibernate-configuration >

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<? 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:aop = "http://www.springframework.org/schema/aop"
     xmlns:tx = "http://www.springframework.org/schema/tx"
     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.1.xsd
         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
 
     <!-- 配置自动扫描的包 -->
     < context:component-scan  base-package = "com.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.initialPoolSize}" ></ 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 >
         <!-- 配置Hibern配置文件的位置及名称 -->
         < property  name = "configLocation"  value = "classpath:hibernate.cfg.xml" ></ property >
         <!-- 配置Hibernate映射文件的位置及名称,可以只用通配符 -->
         < property  name = "mappingLocations"  value = "com/spring/hibernate/entity/*.hbm.xml" ></ property >
     </ bean >
 
     <!-- 配置Spring的声明式事务 -->
     <!-- 1.配置事务管理器 -->
     < bean  id = "transactionManager"  class = "org.springframework.orm.hibernate4.HibernateTransactionManager" >
         < property  name = "sessionFactory"  ref = "sessionFactory"  />
     </ bean >
     <!-- 2.配置事务属性,需要事务管理器 -->
     < 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 >
     <!-- 3.配置事务切点,并把切点和事务属性关联起来 -->
     < aop:config >
         < aop:pointcut  expression = "execution(* com.spring.hibernate.service.*.*(..))"  id = "txPointcut" />
         < aop:advisor  advice-ref = "txAdvice"  pointcut-ref = "txPointcut" />
     </ aop:config >
</ beans >


测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public  class  SpringHibernateTest {
 
     private  ApplicationContext applicationContext =  null ;
     private  BookShopService bookShopService =  null ;
     private  Cashier cashier =  null ;
     {
         applicationContext =  new  ClassPathXmlApplicationContext( "applicationContext.xml" );
         bookShopService = applicationContext.getBean(BookShopService. class );
         cashier = applicationContext.getBean(Cashier. class );
     }
     
     @Test
     public  void  test3() {
         cashier.checkout( "umgsai" , Arrays.asList( "1001" , "1002" ));
     }
     
     @Test
     public  void  test2() {
         bookShopService.purchase( "umgsai" "1001" );
     }
     
     @Test
     public  void  test1() {
         DataSource dataSource = applicationContext.getBean(DataSource. class );
         try  {
             System.out.println(dataSource.getConnection());
         catch  (SQLException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
     }
}


可以把Hibernate的属性信息配置到applicationContext.xml中,这样就可以省略hibernate.cfg.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 配置Hibernate的SessionFactory实例:通过Spring提供的LocalSessionFactoryBean进行配置 -->
     < bean  id = "sessionFactory"  class = "org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
         <!-- 配置数据源属性 -->
         < property  name = "dataSource"  ref = "dataSource" ></ property >
         <!-- 配置Hibern配置文件的位置及名称 -->
         <!--  
         <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
         -->
         < 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" >update</ prop >
             </ props >
         </ property >
         <!-- 配置Hibernate映射文件的位置及名称,可以只用通配符 -->
         < property  name = "mappingLocations"  value = "com/spring/hibernate/entity/*.hbm.xml" ></ property >
     </ bean >

你可能感兴趣的:(spring整合hibernate)