Spring第13篇—–Spring整合Hibernate之声明式事务管理
不容置疑的我们可以知道Spring的事务管理是通过AOP(AOP把我们的事务管理织入到我们的业务逻辑里面了)的方式来实现的,因为事务方面的代码与spring的绑定并以一种样板式结构使用。(面向切面编程)其中的事务通知由元数据(目前基于xml和注解)驱动。代理对象由元数据结合产生一个新的代理对象。他使用一个PlatformTransactionManager实现配合TransactionInterceptor在方法调用之前实施事务。
事务加在DAO层还是Service层?
一般都是放在service层上,因为这层会调用dao层,而service层中某个类里的方法调用的不仅仅只是dao里面的一个方法,有可能是多个方法 一起调用,如果调用的这些方法中有一个不成功或抛出异常,就必须全部返回到以前的数据(回滚),所以就必须将这个service层中某个类里的方法进行管理,这就是用到了spring里的事务管理,所以都是事务管理一般都是用在service层中。
采用注解方式配置事务:
配置文件:
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
56
57
|
<?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-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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd " >
<context:component-scan base-package="net.zmcheng"/>
<bean id=" logInterceptor" class="net.zmcheng.aop.LogInterceptor"/>
<aop:config>
<aop:pointcut expression="execution(public * net.zmcheng.serviceImpl.UserServiceImpl.add())" id="servicePointCut"/>
<aop:aspect id="logAspect" ref=" logInterceptor">
<aop:before method="before" pointcut-ref="servicePointCut"/>
<aop:around method="aroundMethod" pointcut-ref="servicePointCut"/>
</aop:aspect>
</aop:config>
<!-- 设置数据源:提供了一个标准化的取得数据库连接的方式,一看到property我们就应该有一个意识,那就是这个类当中有这个属性的setter方法来进行注入 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/BSWS?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<!-- 整合Hibernate -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 使用注解的方式
<property name="annotatedClasses">
<list><value>net.zmcheng.model.NlUser</value></list>
</property>
-->
<property name="mappingResources">
<list>
<value>net/zmcheng/model/NlUser.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- 声明式事务 -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 采用@Transactional注解方式使用事务 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
|
PS:经测试需要加入spring-jdbc-4.0.0.RELEASE-javadoc.jar。
服务层:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package net.zmcheng.serviceImpl;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import net.zmcheng.dao.UserDao;
import net.zmcheng.service.UserService;
@Component
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//注意引用的是Spring提供的事务
@Transactional
public void add() {
userDao.add();
}
}
|
DAO层:
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
|
package net.zmcheng.daoImpl;
import javax.annotation.Resource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Component;
import net.zmcheng.dao.UserDao;
import net.zmcheng.model.NlUser;
@Component
public class UserDaoImpl implements UserDao {
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Resource
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private SessionFactory sessionFactory;
public void add() {
/*不要再使用getSession,因为每次调用它都是产生一个新的Session
Session s = sessionFactory.openSession();*/
Session session = sessionFactory.getCurrentSession();
NlUser n = new NlUser();
n.setName("zmcheng");
session.save(n);
System.out.println("添加员工成功");
}
}
|
PS:任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚,这些默认的设置当然也是可以被改变的。
采用XML方式配置事务(大多数情况下):
我们想施加的事务语义封装在<tx:advice/>定义中。<tx:advice/> “把所有以 ‘get’ 开头的方法看做执行在只读事务上下文中, 其余的方法执行在默认语义的事务上下文中”。 其中的 ‘transaction-manager’ 属性被设置为一个指向 PlatformTransactionManager bean的名字(这里指 ‘txManager’), 该bean将会真正管理事务。配置中最后一段是 <aop:config/> 的定义, 它确保由 ‘txAdvice’ bean定义的事务通知在应用中合适的点被执行。 首先我们定义了 一个切面,然后我们用一个通知器(advisor)把这个切面与 ‘txAdvice’ 绑定在一起, 表示当 ‘fooServiceOperation’ 执行时,’txAdvice’ 定义的通知逻辑将被执行。
配置文件:
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
56
57
58
59
60
|
<?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-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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd " >
<context:component-scan base-package="net.zmcheng"/>
<!-- 设置数据源:提供了一个标准化的取得数据库连接的方式,一看到property我们就应该有一个意识,那就是这个类当中有这个属性的setter方法来进行注入 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/BSWS?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<!-- 整合Hibernate -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 使用注解的方式
<property name="annotatedClasses">
<list><value>net.zmcheng.model.NlUser</value></list>
</property>
-->
<property name="mappingResources">
<list>
<value>net/zmcheng/model/NlUser.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- 声明式事务 -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 采用@Transactional注解方式使用事务
<tx:annotation-driven transaction-manager="txManager"/>-->
<bean id=" logInterceptor" class="net.zmcheng.aop.LogInterceptor"/>
<aop:config>
<aop:pointcut expression="execution(public * net.zmcheng.serviceImpl..*.*(..))" id="servicePointCut"/>
<aop:advisor pointcut-ref="servicePointCut" advice-ref="txAdvice"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
</beans>
|
DAO:
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
|
package net.zmcheng.daoImpl;
import javax.annotation.Resource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Component;
import net.zmcheng.dao.UserDao;
import net.zmcheng.model.NlUser;
@Component
public class UserDaoImpl implements UserDao {
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Resource
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private SessionFactory sessionFactory;
public void add() {
/*不要再使用getSession,因为每次调用它都是产生一个新的Session
Session s = sessionFactory.openSession();*/
Session session = sessionFactory.getCurrentSession();
NlUser n = new NlUser();
n.setName("zmchen");
session.save(n);
System.out.println("添加员工成功");
}
}
|
事务传播属性(propagation):默认为REQUIRED
REQUIRED:业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务。
NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为它开启事务。如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行。
REQUIRESNEW:属性表明不管是否存在事务,业务方法总会为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方法执行结束,新事务才算结束,原先的事务才会恢复执行。 MANDATORY:该属性指定业务方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果业务方法在没有事务的环境下调用,容器就会抛出例外。
SUPPORTS:这一事务属性表明,如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分。如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。
Never:指定业务方法绝对不能在事务范围内执行。如果业务方法在某个事务中执行,容器会抛出例外,只有业务方法没有关联到任何事务,才能正常执行。
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSource -TransactionManager事务管理器起效。
自动扫描实体类的配置(需要使用注解):
1
2
3
4
5
6
|
<!-- 使用packagesToScan -->
<property name="packagesToScan">
<list>
<value>net.zmcheng.model</value>
</list>
</property>
|
PS:因为我看的视频是spring3.0里面还在讲HibernateTemplate(原理是利用了模板设计模),本来想想一篇博客的,一查文档发现文档里说hibernate4+spring集成推荐用sessionFactory.getCurrentSession(),在Spring与hibernate4的整合中,已经取消了HibernateTemplate和HibernateDaoSupport这两个方法只能通过session来进行处理。如果想使用只能自己实现。
Spring第13篇—–Spring整合Hibernate之声明式事务管理的更多相关文章
- Spring Boot 揭秘与实战(二) 数据存储篇 - 声明式事务管理
文章目录 1. 声明式事务 2. Spring Boot默认集成事务 3. 实战演练4. 源代码 3.1. 实体对象 3.2. DAO 相关 3.3. Service 相关 3.4. 测试,测试 本文 ...
- 全面分析 Spring 的编程式事务管理及声明式事务管理
开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...
- 全面分析 Spring 的编程式事务管理及声明式事务管理--转
开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...
- spring声明式事务管理方式( 基于tx和aop名字空间的xml配置+@Transactional注解)
1. 声明式事务管理分类 声明式事务管理也有两种常用的方式, 一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解. 显然基于注解的方式更简单易用,更清爽. ...
- Spring编程式事务管理及声明式事务管理
本文将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. Spring 事务属性分析 事务管理 ...
- Spring—SSJ集成&声明式事务管理
1. 课程介绍 1. SSJ集成;(掌握) 2. 声明式事务管理;(掌握) 什么是三大框架 2.1. ssh Struts/Struts2 Spring Hibernate 2.2. ss ...
- 【Spring】Spring的事务管理 - 2、声明式事务管理(实现基于XML、Annotation的方式。)
声明式事务管理 文章目录 声明式事务管理 基于XML方式的声明式事务 基于Annotation方式的声明式事务 简单记录 - 简单记录-Java EE企业级应用开发教程(Spring+Spring M ...
- spring声明式事务管理总结
事务配置 首先在/WEB-INF/applicationContext.xml添加以下内容: <!-- 配置事务管理器 --> <bean id="transactionM ...
- Spring声明式事务管理
一.Spring 的声明式事务管理概述 1.Spring 的声明式事务管理在底层是建立在 AOP 的基础之上的.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法 ...
随机推荐
- hdu Turn the corner
这题是道三分的题,首先要分析满足条件的情况,这个就是平面几何的功夫了.要想车子能够转弯成功,最上面那个点到水平线的距离要小于等于y.这里h和s的公式就是利用平面几何的知识求出来的:s=l*cos(a) ...
- [转].net中的认证(authentication)与授权(authorization)
本文转自:http://www.cnblogs.com/yjmyzz/archive/2010/08/29/1812038.html 注:这篇文章主要给新手看的,老手们可能会觉得没啥营养,就请绕过吧. ...
- Union大小
在一个union类型结构中,所有的成员公用同样的存储空间,其占用的大小为其成员中需要空间最大者: union本身只保留一块地址空间,因为只有一个成员真正存储于该地址, 但这块地址也要满足内存对齐原则. ...
- dig 命令详解(转载) - 阿权的书房
在 unix 和 linux 下,建议大家使用 dig 命令来代替 nslookup. dig 命令的功能比 nslookup 强大很多,不像 nslookkup 还得 set 来 set 去的,怪麻 ...
- iOS segue 跳转
场景描述: 要实现在tableViewController 的界面A里,点击一个cell ,跳转到第二个viewController的界面B .在第二个界面里做相应操作. 我的做法,利用sb,在A 里 ...
- Js组件的一些写法【转】
首先看下Prototype里的写法: var Class = { create: function() { return function() { this.init.apply(this, argu ...
- PHP程序员必须清楚的问题汇总
PHP程序员必须清楚的问题汇总 投稿:hebedich 字体:[增加 减小] 类型:转载 这篇文章主要介绍了PHP程序员必须清楚的问题汇总,需要的朋友可以参考下 你是否正在准备寻找一份PH ...
- Solr定时更新
今天用到solr定时重建索引和增量更新技术,就从网上搜了一些资料,在这里给大家整理了一下,也经过了自己的测试,没有异常. Solr官方提供了很强大的Data Import Request Handle ...
- but this usually doesn’t gain you anything.
High Performance My SQL, Third Edition Date and Time Types My SQL has many types for various kinds o ...
- 【Demo】HTML5 拍照上传
本文主要讲解 手机浏览器 如何拍照 为什么会有这个需求 最近做一个项目要用到拍照然后上传照片,但是网页拍照一般都是用Flash做的,而我们主要是H5页面,如果在微信里面有权限就可以通过JSSDK调起摄 ...