【问题标题】:Spring @Transactional merge and persist questionSpring @Transactional 合并和持久化问题
【发布时间】:2010-12-07 17:25:01
【问题描述】:

Spring 新手,这里是 @stackoverflow

我正在为分销商业务构建一个独立的库存和销售跟踪应用程序 (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() 来生成报告一样(不需要是事务性的,对吧?)。

谢谢!!!

【问题讨论】:

    标签: java spring jpa


    【解决方案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,(我对灵活性的需求不大)
    猜你喜欢
    • 1970-01-01
    • 2020-06-05
    • 2017-10-10
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    相关资源
    最近更新 更多