Spring @Transactional 合并和持久化问题
Posted
技术标签:
【中文标题】Spring @Transactional 合并和持久化问题【英文标题】:Spring @Transactional merge and persist question 【发布时间】:2010-12-07 17:25:01 【问题描述】:Spring 新手,这里是 @***
我正在为分销商业务构建一个独立的库存和销售跟踪应用程序 (Apache Pivot/Spring/JPA/Hibernate/mysql)。
到目前为止,我认为一切都是 CRUD,所以我计划有一个包含 @Transactional 一切的基类。
然后我的保存通用方法出现问题。 Spring中EntityManager的persist和merge方法有区别吗?
我尝试运行并调用 save 以进行插入和更新,它工作正常(我认为 spring 每次我调用我的 save 方法时都会自动刷新实体 // 看到休眠查询被记录,对吗?)。
@Transactional
public abstract class GenericDAO
protected EntityManager em;
// em getter+@PersistenceContext/setter
public void save(T t)
// if (t.getId() == null) // create new
//
// em.persist(t);
// else // update
//
em.merge(t);
//
顺便说一句,有了这样的设置,我不会对性能造成太大影响,对吧?就像调用 salesDAO.findAll() 来生成报告一样(不需要是事务性的,对吧?)。
谢谢!!!
【问题讨论】:
【参考方案1】:This SO question 很好地讨论了持久化与合并,并且接受的答案很好地解释了它。另一个答案还链接到关于此的一篇很好的博客文章。
根据this other post 的第一个回复,听起来可以调用merge 来保存和更新实体,但我不是这样做的。在我的 Spring/JPA 应用程序中,我只是让我的 DAO 扩展 JpaDaoSupport 并按以下方式使用 getJpaTemplate()。
/**
* Save a new Album.
*/
public Album save(Album album)
getJpaTemplate().persist(album);
return album;
/**
* Update an existing Album.
*/
public Album update(Album album)
return getJpaTemplate().merge(album);
【讨论】:
我来宾这是最简单的方法。因此,如果我有 JpaDaoSupport,并且我从中获得了一个实体,那么任何更改都会自动提交吗?我想我会有两种保存方法的变体,一种是持久的,一种是调用刷新的。对此有何评论? 你的意思是自动提交没有保存或更新?如果是这样,我不这么认为,我总是只在新实体上调用 save 或在现有实体上更新以保持。我从来不需要调用 flush 方法,但是对于任何给定的请求,我的数据库访问都非常简单。 我现在不得不放弃尝试 Spring。只是好奇,Grails 对此有何改进?我不会在 Grails 中遇到类似的问题吧?【参考方案2】:link 到 Kaleb 发布的另一个 SO 问题确实很好地涵盖了 persist() 与 merge() 的差异和陷阱。但是,我一直只是用一个 save() 方法实现我的 Dao 类,该方法只调用 merge() 来处理插入和更新,而且我从来没有遇到任何 persist() 与 merge() 陷阱。
就性能和事务方法而言:
在仅读取操作的方法上使用 @Transactional
不会真正影响性能,尽管我更喜欢在方法级别使用注释,这样我就可以轻松分辨哪些方法是更新的,哪些是读取的。您可以通过在@Transactional
注释上设置readOnly
属性来做到这一点。
如果您在方法中遵循命名约定(即任何读取方法始终以 getXXX
开头),您还可以在 Spring 配置文件中使用切入点语法来自动进行区分:
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
请参阅Spring documentation on Transactions 了解更多信息。
另外,我通常将@Transactional
属性放在我的Dao 类的上一层,在服务层中。 Dao 类上的方法对于每个方法调用都是不同的数据库操作,而服务方法可以为一系列更新执行单个提交/回滚。
【讨论】:
感谢您的回答。我想我会坚持纯 JPA,(我对灵活性的需求不大)以上是关于Spring @Transactional 合并和持久化问题的主要内容,如果未能解决你的问题,请参考以下文章
Spring @Transactional 和 Spring @Lock 注解有啥关系?
Spring @Transactional 和 @Async