Spring @Transactional合并并坚持提问

时间:2009-10-18 04:06:15

标签: java spring jpa

Spring的新手和@stackoverflow

我正在建立一个独立的库存&销售跟踪应用程序(Apache Pivot / Spring / JPA / Hibernate / MySQL),用于分销商业务。

到目前为止,我认为一切都是CRUD,所以我计划在@Transactional上设置一个基类。

然后我的保存通用方法出了问题。从Spring继承和合并EntityManager的方法有区别吗?

我尝试运行并调用了插入和更新的保存并且它工作正常(我认为每次调用我的保存方法时spring会自动刷新实体//看到hibernate查询被记录,这是对的吗?)。< / p>

@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()来生成报告一样(不需要是事务性的,对吗?)。

感谢!!!

2 个答案:

答案 0 :(得分:5)

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);
}

答案 1 :(得分:4)

Kaleb发布的另一个SO问题的link确实很好地弥补了persist()vs merge()的差异和陷阱。但是,我总是用一个save()方法实现我的Dao类,该方法只调用merge()来处理插入和更新,而且我从来没有碰到任何persist()vs merge()陷阱。 / p>

就性能和交易方法而言: 在只读取操作的方法上使用@Transactional不会真正影响性能,但我更喜欢在方法级别上使用注释,这样我就可以很容易地判断哪些方法是更新,哪些方法是读取。您可以通过在readOnly注释上设置@Transactional属性来执行此操作。

如果您遵循方法中的命名约定(即任何读取方法始终以getXXX开头),您还可以在Spring配置文件中使用poincut语法自动进行区分:

  <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类上的方法是每个方法调用的不同数据库操作,而服务方法可以为一系列更新执行单个提交/回滚。