如何在Spring容器之外使用Spring Data JPA? [英] How do you use Spring Data JPA outside of a Spring Container?

查看:114
本文介绍了如何在Spring容器之外使用Spring Data JPA?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试手动连接Spring Data JPA对象,以便我可以生成DAO代理(也称为存储库) - 而不使用Spring bean容器。

I'm trying to wire up Spring Data JPA objects manually so that I can generate DAO proxies (aka Repositories) - without using a Spring bean container.

不可避免地,我会被问到为什么要这样做:这是因为我们的项目已经在使用Google Guice(并且在使用Gin和GWT的UI上),我们不想维护另一个IoC容器配置,或者全部拉入产生的依赖关系。我知道我们可以使用Guice的 SpringIntegration ,但这是最后的选择。

Inevitably, I will be asked why I want to do this: it is because our project is already using Google Guice (and on the UI using Gin with GWT), and we don't want to maintain another IoC container configuration, or pull in all the resulting dependencies. I know we might be able to use Guice's SpringIntegration, but this would be a last resort.

似乎一切都可用于手动连接对象,但由于没有详细记录,我现在遇到困难。

It seems that everything is available to wire the objects up manually, but since it's not well documented, I'm having a difficult time.

根据Spring Data用户指南,使用< a href =http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/#repositories.create-instances.standalone =noreferrer>存储库工厂独立是可能的。不幸的是,该示例显示了 RepositoryFactorySupport 这是一个抽象类。经过一番搜索,我找到了 JpaRepositoryFactory

According to the Spring Data user's guide, using repository factories standalone is possible. Unfortunately, the example shows RepositoryFactorySupport which is an abstract class. After some searching I managed to find JpaRepositoryFactory

JpaRepositoryFactory 实际上工作得很好,除了它不会自动创建事务。必须手动管理事务,否则任何内容都不会持久存储到数据库:

JpaRepositoryFactory actually works fairly well, except it does not automatically create transactions. Transactions must be managed manually, or nothing will get persisted to the database:

entityManager.getTransaction().begin();
repositoryInstance.save(someJpaObject);
entityManager.getTransaction().commit();

问题原因是 @Transactional 注释不会自动使用,需要 TransactionInterceptor的帮助

The problem turned out to be that @Transactional annotations are not used automatically, and need the help of a TransactionInterceptor

谢天谢地, JpaRepositoryFactory 可以在返回之前接受回调以向生成的存储库代理添加更多AOP建议:

Thankfully, the JpaRepositoryFactory can take a callback to add more AOP advice to the generated Repository proxy before returning:

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 。 Spring通过查看当前正在执行的线程来管理活动的 EntityManager TransactionInterceptor 执行此操作,并且看到没有活动的 EntityManager 绑定到该线程,并决定创建一个新的。

This is where things are not working out so well. Stepping through the debugger in the code, the TransactionInterceptor is indeed creating a transaction - but on the wrong EntityManager. Spring manages the active EntityManager by looking at the currently executing thread. The TransactionInterceptor does this and sees there is no active EntityManager bound to the thread, and decides to create a new one.

然而,这个新的 EntityManager 与创建并传递到 JpaRepositoryFactory 构造函数,需要 EntityManager 。问题是,如何使 TransactionInterceptor JpaRepositoryFactory 使用相同的 EntityManager

However, this new EntityManager is not the same instance that was created and passed into the JpaRepositoryFactory constructor, which requires an EntityManager. The question is, how do I make the TransactionInterceptor and the JpaRepositoryFactory use the same EntityManager?

在写这篇文章时,我发现了如何解决问题但它仍然可能不是理想的解决方案。我将此解决方案作为单独的答案发布。我很高兴听到有关更好地使用Spring Data JPA独立方法的建议,而不是我如何解决它。

While writing this up, I found out how to solve the problem but it still may not be the ideal solution. I will post this solution as a separate answer. I would be happy to hear any suggestions on a better way to use Spring Data JPA standalone than how I've solve it.

推荐答案

设计 JpaRepositoryFactory 背后的一般原则和相应的Spring集成 JpaRepositoryFactory bean如下:

The general principle behind the design of JpaRepositoryFactory and the according Spring integration JpaRepositoryFactory bean is the following:


我们假设你在托管的 JPA运行时环境中运行你的应用程序,而不是关心哪一个。

We're assuming you run your application inside a managed JPA runtime environment, not caring about which one.

这就是我们依赖注入 EntityManager 而不是 EntityManagerFactory的原因。根据定义, EntityManager 不是线程安全的。因此,如果直接处理 EntityManagerFactory ,我们将不得不重写托管运行时环境(就像Spring或EJB)将为您提供的所有资源管理代码。

That's the reason we rely on injected EntityManager rather than an EntityManagerFactory. By definition the EntityManager is not thread safe. So if dealt with an EntityManagerFactory directly we would have to rewrite all the resource managing code a managed runtime environment (just like Spring or EJB) would provide you.

为了与Spring事务管理集成,我们使用Spring的 SharedEntityManagerCreator 来实际执行您手动实现的事务资源绑定魔法。因此,您可能希望使用该实例从 EntityManagerFactory 创建 EntityManager 实例。如果要直接激活存储库bean中的事务性(以便调用例如 repo.save(...)创建一个事务(如果没有活动),请查看在Spring Data Commons中的 TransactionalRepositoryProxyPostProcessor 实现。它实际上在直接使用Spring Data存储库时激活事务(例如,对于 repo.save(...))并稍微自定义事务配置查找以优先于实现类的接口以允许存储库用于覆盖 SimpleJpaRepository 中定义的事务配置的接口。

To integrate with the Spring transaction management we use Spring's SharedEntityManagerCreator that actually does the transaction resource binding magic you've implemented manually. So you probably want to use that one to create EntityManager instances from your EntityManagerFactory. If you want to activate the transactionality at the repository beans directly (so that a call to e.g. repo.save(…) creates a transaction if none is already active) have a look at the TransactionalRepositoryProxyPostProcessor implementation in Spring Data Commons. It actually activates transactions when Spring Data repositories are used directly (e.g. for repo.save(…)) and slightly customizes the transaction configuration lookup to prefer interfaces over implementation classes to allow repository interfaces to override transaction configuration defined in SimpleJpaRepository.

这篇关于如何在Spring容器之外使用Spring Data JPA?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆