Fil*_*Fil 10 java spring synchronization jpa transactions
我正在使用JPA EntityListener来执行一些额外的审计工作,并使用@Configurable将Spring管理的AuditService注入到AuditEntryListener中.AuditService生成AuditEntry对象的集合.AuditService本身就是一个Singleton范围的bean,我想收集一个公共密钥下的所有AuditEntry对象,然后可以由最外层的服务层(调用persist调用,然后触发EntityListener)访问.
我正在考虑使用Spring的TransactionSynchronizationManager在事务开始时设置一个特定的事务名称(使用UID()或其他一些独特的策略),然后使用该名称作为AuditService中的一个键,允许我对所有组进行分组在该事务中创建的AuditEntry对象.
混合声明式和程序式事务管理是否有可能出现问题?(虽然我只是设置事务名称).有没有更好的方法将生成的AuditEntry对象与当前事务相关联?这个解决方案对我有用,但鉴于TransactionSynchronizationManager不是供应用程序使用,我想确保我对它的使用不会导致一些不可预见的问题.
最后,一个相关的,但不是直接相关的问题:我知道JPA EntityListeners的文档警告不要使用当前的EntityManager,但如果我确实想用它来区分对象的持久化自我,我是否可以安全地使用@围绕我的preUpdate()方法的事务性(传播= REQUIRES_NEW)注释?
服务类
@Transactional
public void create(MyEntity e) {
TransactionSynchronizationManager.setCurrentTransactionName(new UID().toString());
this.em.persist(e);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
Set<AuditEntry> entries = auditService.getAuditEntries(TransactionSynchronizationManager.getCurrentTransactionName());
if(entries != null) {
for(AuditEntry entry : entries) {
//do some stuff....
LOG.info(entry.toString());
}
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
JPA EntityListener
@Configurable
public class AuditEntryListener {
@Autowired
private AuditService service;
@PreUpdate
public void preUpdate(Object entity) {
service.auditUpdate(TransactionSynchronizationManager.getCurrentTransactionName(), entity);
}
public void setService(AuditService service) {
this.service = service;
}
public AuditService getService() {
return service;
}
Run Code Online (Sandbox Code Playgroud)
}
AuditService
@Service
public class AuditService {
private Map<String, Set<AuditEntry>> auditEntryMap = new HashMap<String, Set<AuditEntry>>();
public void auditUpdate(String key, Object entity) {
// do some audit work
// add audit entries to map
this.auditEntryMap.get(key).add(ae);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用 TransactionSynchronizationManager 提出解决方案。我们向 JPA 注册一个“TransactionInterceptorEntityListener”作为实体侦听器。我们想要实现的是侦听 CRUD 事件的能力,以便我们可以使用 spring 管理的“侦听器”,该“侦听器”的生命周期与当前事务相关(即,spring 管理但每个事务都有一个实例)。我们对 JPATransactionManager 进行子类化,并在prepareSynchronization() 方法中引入一个用于设置“TransactionInterceptorSynchronizer”的挂钩。我们还使用相同的钩子来允许代码(在编程交易中)将任意对象与当前事务关联并检索,并注册在事务提交之前/之后运行的作业。
整体代码比较复杂,但是绝对可行。如果您使用 JPATemplates 进行编程式交易,则很难实现这一点。因此,我们推出了自己的模板,在处理完拦截器工作后简单地调用 JPA 模板。我们计划很快开源我们的 JPA 库(写在 Spring 的类之上)。
您可以在以下 Postgresql 库中看到添加自定义事务和与 Spring 托管事务挂钩的模式
归档时间: |
|
查看次数: |
2661 次 |
最近记录: |