Spring和@stackoverflow的新手
我正在为分销商业务构建一个独立的库存和销售跟踪应用程序(Apache Pivot/Spring/JPA/Hibernate/MySQL).
到目前为止,我认为一切都是CRUD,所以我计划有一个基础类,包含@Transactional.
然后我的save泛型方法出了问题.从Spring继承和合并EntityManager的方法有区别吗?
我试着运行并调用了插入和更新的保存,它运行正常(我认为每次调用我的保存方法时,spring会自动刷新实体//看到hibernate查询被记录,这是对的吗?).
@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);
// }
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,有了这样的设置,我不会在很大程度上影响性能吗?就像调用salesDAO.findAll()来生成报告一样(不需要是事务性的,对吧?).
谢谢!!!
这个问题是对持久性与合并的良好讨论,并且接受的答案很好地解释了它.另一个答案也链接到一篇关于此的好博文.
根据这篇文章中的第一篇回复,听起来有可能为了保存和更新实体而调用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);
}
Run Code Online (Sandbox Code Playgroud)
Kaleb 发布的另一个 SO 问题的链接确实很好地涵盖了 persist() 与 merge() 的差异和陷阱。但是,我总是使用一个只调用 merge() 来处理插入和更新的 save() 方法来实现我的 Dao 类,而且我从未遇到过任何 persist() 与 merge() 问题。
至于性能和事务方法:使用@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>
Run Code Online (Sandbox Code Playgroud)
此外,我通常将@Transactional
属性放在我的 Dao 类之上一级,在服务层中。Dao 类上的方法对于每个方法调用都是不同的数据库操作,而服务方法可以为一系列更新执行单个提交/回滚。