博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【spring框架】spring使用XML进行声明式事务管理
阅读量:6207 次
发布时间:2019-06-21

本文共 5376 字,大约阅读时间需要 17 分钟。

d)xml(推荐,可以同时配置好多方法)
请看下面的接口和它的实现。这个例子的意图是介绍概念,使用 Foo 和 Bar 这样的名字只是为了让你关注于事务的用法,而不是领域模型。
// 我们想做成事务性的服务接口
package x.y.service;public interface FooService {  Foo getFoo(String fooName);  Foo getFoo(String fooName, String barName);  void insertFoo(Foo foo);  void updateFoo(Foo foo);}
// 上述接口的一个实现
package x.y.service;public class DefaultFooService implements FooService {  public Foo getFoo(String fooName) {    throw new UnsupportedOperationException();  }  public Foo getFoo(String fooName, String barName) {    throw new UnsupportedOperationException();  }  public void insertFoo(Foo foo) {    throw new UnsupportedOperationException();  }  public void updateFoo(Foo foo) {    throw new UnsupportedOperationException();  }}
(对该例的目的来说,上例中实现类(DefaultFooService)的每个方法在其方法体中抛出 UnsupportedOperationException 的做法是恰当的,我们可以看到,事务被创建出来, 响应 UnsupportedOperationException 的抛出,然后回滚。) 
我们假定,FooService的前两个方法(getFoo(String) 和getFoo(String, String))必须执行在只读事务上下文中,其他的方法(insertFoo(Foo)和 updateFoo(Foo))必须执行在可读写事务上下文中。不要想着一次理解下面的配置,所有内容都会在后面的章节详细讨论。
我们来分析一下上面的配置。我们要把一个服务对象('fooService' bean)做成事务性的。 我们想施加的事务语义封装在<tx:advice/>定义中。<tx:advice/> “把所有以 'get' 开头的方法看做执行在只读事务上下文中, 其余的方法执行在默认语义的事务上下文中”。 其中的 'transaction-manager' 属性被设置为一个指向 PlatformTransactionManager bean的名字(这里指 'txManager'), 该bean将会真正管理事务。
提示
事实上,如果 PlatformTransactionManager bean的名字是 'transactionManager' 的话,你的事务通知(<tx:advice/>)中的 'transaction-manager' 属性可以忽略。否则你则需要像上例那样明确指定。
配置中最后一段是 <aop:config/> 的定义, 它确保由 'txAdvice' bean定义的事务通知在应用中合适的点被执行。 首先我们定义了 一个切面,它匹配 FooService 接口定义的所有操作, 我们把该切面叫做 'fooServiceOperation'。然后我们用一个通知器(advisor)把这个切面与 'txAdvice' 绑定在一起, 表示当 'fooServiceOperation' 执行时,'txAdvice' 定义的通知逻辑将被执行。
<aop:pointcut/> 元素定义是AspectJ的切面表示法,可参考Spring 2.0 第 6 章 使用Spring进行面向切面编程(AOP)章获得更详细的内容。
一个普遍性的需求是让整个服务层成为事务性的。满足该需求的最好方式是让切面表达式匹配服务层的所有操作方法。例如:
(这个例子中假定你所有的服务接口定义在 'x.y.service' 包中。你同样可以参考 第 6 章 使用Spring进行面向切面编程(AOP) 章获得更详细内容。) 
现在,既然我们已经分析了整个配置,你可能会问了,“好吧,但是所有这些配置做了什么?”。
上面的配置将为'fooService' bean创建一个代理对象,这个代理对象被装配了事务通知,所以当它的相应方法被调用时,一个事务将被启动、挂起、被标记为只读,或者其它(根据该方法所配置的事务语义)。
上面是官方的文档,下面我们自己测试一下
beans.xml:
classpath:com/foo/jdbc.properties
cn.edu.hpu.model.User
cn.edu.hpu.model.Log
org.hibernate.dialect.MySQLDialect
true
Service层:
UserService.java:
package cn.edu.hpu.service;import javax.annotation.Resource;import org.springframework.stereotype.Component;import org.springframework.transaction.annotation.Transactional;import cn.edu.hpu.dao.LogDao;import cn.edu.hpu.dao.UserDao;import cn.edu.hpu.model.Log;import cn.edu.hpu.model.User;@Component("userService")public class UserService {	private UserDao userDao;	public void init(){		System.out.println("init");	}		public UserDao getUserDao() {		return userDao;	}		@Resource(name="u")	public void setUserDao(UserDao userDao) {		this.userDao = userDao;	}		public LogDao getLogDao() {		return logDao;	}		@Resource(name="logDao")	public void setLogDao(LogDao logDao) {		this.logDao = logDao;	}	public void add(User u){		this.userDao.save(u);		Log log=new Log();		log.setMsg("a user saved!");		this.logDao.save(log);	}		public void destroy(){		System.out.println("destroy");	}	}
UserDaoOmpl.java:
package cn.edu.hpu.dao.Impl;import javax.annotation.Resource;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.stereotype.Component;import cn.edu.hpu.dao.UserDao;import cn.edu.hpu.model.User;@Component("u")public class UserDaoImpl implements UserDao{		private SessionFactory sessionFactory;		public SessionFactory getSessionFactory() {		return sessionFactory;	}		@Resource	public void setSessionFactory(SessionFactory sessionFactory) {		this.sessionFactory = sessionFactory;	}	public void save(User u) {		Session s=sessionFactory.getCurrentSession();		s.save(u);		System.out.println("add success!!");			}}
测试:
package cn.edu.hpu.service;import org.junit.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.edu.hpu.model.User;public class UserServiceTest {		@Test	public void testAdd() throws Exception{		ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");				UserService userService=(UserService)ctx.getBean("userService");		System.out.println(userService.getClass());		User u=new User();		u.setName("jack");		userService.add(u);		ctx.destroy();	}}
测试结果:
class cn.edu.hpu.service.UserService $ $ EnhancerByCGLIB $ $ c43f0270
Hibernate: insert into User (name) values (?)
add success!!
Hibernate: insert into t_log (msg) values (?)

测试成功!

转载请注明出处:

你可能感兴趣的文章
记录一次批量处理文档的过程
查看>>
Webstorm2016使用技巧——SVN插件使用(svnToolBox)
查看>>
扩展 Windows Azure 运营能力 – 巴西
查看>>
android EditText长按屏蔽ActionMode context菜单但保留选择工具功能
查看>>
微信小程序左右滑动切换页面示例代码--转载
查看>>
大道至简:软件工程实践者的思想第二章读后感
查看>>
Floodlight中 处理packetin消息的顺序(2)
查看>>
服务器80端口被占用
查看>>
vue.js 解决空格报错!!!
查看>>
Sql Server数据库笔记
查看>>
实现jQuery扩展总结
查看>>
C2 shell
查看>>
【jQuery】关于选择器中的 :first 、 :first-child 、 :first-of-type
查看>>
linux下安装虚拟环境
查看>>
dom 解析xml文件
查看>>
演示:Linux工程环境应用实训(防火墙、NAT、静态路由)详细配步骤
查看>>
Tip:强制执行exchange DAG节点之间的数据库副本移动
查看>>
[你必须知道的异步编程]——异步编程模型(APM)
查看>>
基于积分墙盈利模式的APP架构思考
查看>>
专访:混合云的发展趋势
查看>>