Spring AOP 在 Hibernate 事务管理

事务管理是用来以确保数据库中数据的完整性和一致性。Spring AOP 技术允许开发者管理事务的声明。下面这个例子来说明如何使用 Spring AOP 来管理 Hibernate 事务。在上一篇 Spring 整合 Hibernate 注解方式 文章的基础上。

1. 再创建一张表

CREATE TABLE `comment` (
  `cid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `aid` int(10) unsigned NOT NULL,
  `comment_content` varchar(254) NOT NULL DEFAULT '',
  `postedby` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`cid`)
);

2. Comment的数据访问对象和业务对象

public interface CommentDao {
	public void insert(Comment comment);
	public void update(Comment comment);
	public void delete(Comment comment);
	
	public List<Comment> getComments();
	public Comment getCommentById(int id);
}

@Component("commentDao")
public class CommentDaoImpl extends HibernateDaoSupport implements CommentDao {

	@Resource
	public void setMySessionFactory(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
	public void insert(Comment comment) {
		getHibernateTemplate().save(comment);
	}
	public void update(Comment comment) {
		getHibernateTemplate().update(comment);
	}
	public void delete(Comment comment) {
		getHibernateTemplate().delete(comment);
	}
	public List<Comment> getComments() {
		return (List<Comment>) getHibernateTemplate().find("from Comment");
	}
	public Comment getCommentById(int id) {
		return (Comment) getHibernateTemplate().find("from Comment where cid = ?", id).get(0);
	}
}
public interface CommentService {
	public void save(Comment comment);
	public void update(Comment comment);
	public void remove(Comment comment);
	
	public List<Comment> findComments();
	public Comment findCommentById(int id);
}

@Service("commentService")
public class CommentServiceImpl implements CommentService {
	private CommentDao commentDao;
	@Autowired	
	public void setCommentDao(CommentDao commentDao) {
		this.commentDao = commentDao;
	}
	public void save(Comment comment) {
		commentDao.insert(comment);
	}
	public void update(Comment comment) {
		commentDao.update(comment);
	}
	public void remove(Comment comment) {
		commentDao.delete(comment);
	}
	public List<Comment> findComments() {
		return commentDao.getComments();
	}
	public Comment findCommentById(int id) {
		return commentDao.getCommentById(id);
	}
}

 3. Article的业务对象修改如下

@Transactional(propagation=Propagation.REQUIRED)
@Service("articleService")
public class ArticleServiceImpl implements ArticleService {
	
	private ArticleDao articleDao;
	private CommentService commentService;
	
	@Autowired
	public void setArticleDao(ArticleDao articleDao) {
		this.articleDao = articleDao;
	}
	@Autowired
	public void setCommentService(CommentService commentService) {
		this.commentService = commentService;
	}

	public void save(Article article) {
		articleDao.insert(article);
		
		Comment comment = new Comment();
		comment.setCommentcontent(article.getTitle() + "写得很好");
		comment.setPostedBy("Angelia(默认)");
		comment.setArticleId(article.getId());
		//int i= 1/0;
		commentService.save(comment);
	}
	public void update(Article article) {
		articleDao.update(article);
	}
	public void remove(Article article) {
		articleDao.delete(article);
	}
	public List<Article> findArticles() {
		return articleDao.getArticles();
	}
	public Article findArticleById(int id) {
		return articleDao.getArticleById(id);
	}
}

4. 配置文件

<hibernate-configuration>
    <session-factory>
        <!-- 配置Hibernate的基本属性 -->
        <!-- 1.数据源配置到IOC容器中 -->
        <!-- 2.关联的.hbm.xml也在IOC容器配置SessionFactory实例 -->
        <!-- 3.配置Hibernate的基本属性:方言,SQL显示及格式化,生成数据表的策略以及二级缓存 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hbm2ddl.auto">update</property>
        
        <!-- <mapping resource="Article.hbm.xml"/> -->
        <mapping class="com.angelia.sh.model.Article"/>
        <mapping class="com.angelia.sh.model.Comment"/>
    </session-factory>
</hibernate-configuration>
<!-- 配置Spring声明式事务 -->
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

5. 执行测试类,发现如果执行成功,同时向article和comment各插入一条数据。如果失败,即comment保存之前执行“int i= 1/0;”,则两条数据都插入失败。如果去掉@Transactional(propagation=Propagation.REQUIRED)注解,comment保存之前执行“int i= 1/0;”,只保存了一条数据在库里。

Propagation.REQUIRED是事务传播属性。在事务定义中,必须定义的事务的属性“传播行为”。这意味着,如果一个事务“ArticleServiceImpl.save()方法被调用另外的”commentService.save()'方法,事务应该怎么传播。它是继续在现有的事务中运行,还是为自己开始一个新的事务。

下面是Spring支持的7种事务传播属性:

  •     PROPAGATION_REQUIRED – 支持当前事务,如果不存在则创建一个新的。
  •     PROPAGATION_SUPPORTS – 支持当前事务,如果不存在执行非事务。
  •     PROPAGATION_MANDATORY – 支持当前事务,如果当前不存在事务抛出异常。
  •     PROPAGATION_REQUIRES_NEW – 创建一个新的事务,如果当前事务暂停。
  •     PROPAGATION_NOT_SUPPORTED – 不支持当前的事务,而始终执行非事务。
  •     PROPAGATION_NEVER – 不支持当前的事务,如果当前事务存在则抛出异常。
  •     PROPAGATION_NESTED – 如果当前存在事务嵌套事务中执行,表现与 PROPAGATION_REQUIRED 一样。

在大多数情况下,可能只需要使用PROPAGATION_REQUIRED。

Spring 事务除了有传播属性,还有隔离级别。下面是Spring支持的五个隔离级别(后面四个与JDBC的隔离级别相对应):
ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

注:1)幻读:事务1读取记录时事务2增加了记录并提交,事务1再次读取时可以看到事务2新增的记录;
2)不可重复读取:事务1读取记录时,事务2更新了记录并提交,事务1再次读取时可以看到事务2修改后的记录;
3)脏读:事务1更新了记录,但没有提交,事务2读取了更新后的行,然后事务T1回滚,现在T2读取无效。

代码下载链接: https://pan.baidu.com/s/1RhusIDwlUVW-r9NvF-9Mnw 密码: k3yn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AngeliaZheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值