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()来生成报告一样(不需要是事务性的,对吗?)。
感谢!!!
答案 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类上的方法是每个方法调用的不同数据库操作,而服务方法可以为一系列更新执行单个提交/回滚。