我正在尝试手动连接 Spring Data JPA 对象,以便我可以生成 DAO 代理(又名存储库)——而不使用 Spring bean 容器。
不可避免地,有人会问我为什么要这样做:因为我们的项目已经在使用 Google Guice(并且在 UI 上使用带有 GWT 的 Gin),并且我们不想维护另一个 IoC 容器配置,或者引入所有由此产生的依赖关系。我知道我们也许可以使用 Guice's SpringIntegration
,但这将是最后的手段。
似乎一切都可以手动连接对象,但由于没有很好的记录,我遇到了困难。
根据 Spring Data 用户指南,可以独立使用存储库工厂。不幸的是,该示例显示了RepositoryFactorySupport
哪个是抽象类。经过一番搜索,我设法找到了JpaRepositoryFactory
JpaRepositoryFactory
实际上工作得很好,除了它不会自动创建事务。事务必须手动管理,否则不会持久保存到数据库中:
entityManager.getTransaction().begin();
repositoryInstance.save(someJpaObject);
entityManager.getTransaction().commit();
问题原来是@Transactional
注释不是自动使用的,需要帮助TransactionInterceptor
值得庆幸的是,JpaRepositoryFactory
可以在返回之前通过回调向生成的 Repository 代理添加更多 AOP 建议:
final JpaTransactionManager xactManager = new JpaTransactionManager(emf);
final JpaRepositoryFactory factory = new JpaRepositoryFactory(emf.createEntityManager());
factory.addRepositoryProxyPostProcessor(new RepositoryProxyPostProcessor() {
@Override
public void postProcess(ProxyFactory factory) {
factory.addAdvice(new TransactionInterceptor(xactManager, new AnnotationTransactionAttributeSource()));
}
});
这就是事情进展不顺利的地方。单步调试代码中的调试器,TransactionInterceptor
确实是在创建一个事务——但在错误的EntityManager
. SpringEntityManager
通过查看当前正在执行的线程来管理活动。执行TransactionInterceptor
此操作并看到线程没有活动EntityManager
绑定,并决定创建一个新绑定。
但是,这个 newEntityManager
与创建并传递给JpaRepositoryFactory
构造函数的实例不同,它需要一个EntityManager
. 问题是,我如何使TransactionInterceptor
和JpaRepositoryFactory
使用相同EntityManager
?
更新:
在写这篇文章时,我发现了如何解决这个问题,但它仍然可能不是理想的解决方案。我将将此解决方案作为单独的答案发布。我很高兴听到任何关于独立使用 Spring Data JPA 的更好方法的建议,而不是我解决它的方法。