当前位置: 首页 > 面试题库 >

如何在Spring容器之外使用Spring Data JPA?

南宫浩皛
2023-03-14
问题内容

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

不可避免地,我会被问到为什么要这样做:这是因为我们的项目已经在使用Google Guice(以及在UI上使用Gin和GWT的UI),并且我们不想维护其他IoC容器配置,也不想插入所有产生的依赖关系。我知道我们也许可以使用Guice's SpringIntegration,但这将是最后的选择。

似乎所有可用的方法都可以手动将对象连接起来,但是由于没有充分记录,因此我很难过。

根据Spring Data用户指南,可以独立使用存储库工厂。不幸的是,该示例显示了RepositoryFactorySupport哪个是抽象类。经过一番搜索,我设法找到了JpaRepositoryFactory

JpaRepositoryFactory实际上工作得很好,只是它不会自动创建事务。必须手动管理事务,否则什么都不会持久化到数据库中:

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

原来的问题是@Transactional注解不会自动使用,需要一个TransactionInterceptor

值得庆幸的是,JpaRepositoryFactory返回之前,可以进行回调以向生成的存储库代理添加更多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确实确实在创建事务-但是错误EntityManagerSpring EntityManager通过查看当前正在执行的线程来管理活动线程。这样TransactionInterceptor就可以看到EntityManager该线程没有活动的绑定,并决定创建一个新的线程。

但是,此新EntityManager实例与创建并传递到JpaRepositoryFactory构造函数的实例不同,后者需要一个EntityManager。现在的问题是,如何让我的TransactionInterceptorJpaRepositoryFactory使用相同的EntityManager


问题答案:

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

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

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

为了与Spring事务管理集成,我们使用Spring的方法SharedEntityManagerCreator,它实际上完成了你手动实现的事务资源绑定魔术。因此,你可能想使用该EntityManager实例从中创建实例EntityManagerFactory。如果你想直接在存储库bean处激活事务性(以便repo.save(…)在没有活动的情况下调用例如创建事务),请查看TransactionalRepositoryProxyPostProcessorSpring Data Commons 中的实现。实际上,当直接使用Spring Data存储库时(例如repo.save(…)),它会激活事务,并略微定制事务配置查找,以使接口优先于实现类,以允许存储库接口覆盖定义的事务配置SimpleJpaRepository



 类似资料:
  • 作为Docker的菜鸟,考虑使用大小为几百千兆字节或更多的SQL服务器进行存储,在我看来,在容器中存储这么多是不可行的。加载一个大文件需要时间,太字节范围内的文件的合理位置是将它与容器分开装载。 在谷歌搜索这些信息几天后,询问社区似乎更符合逻辑。希望一幅画能抵得上千言万语。 SQL Server容器如何装载外部SQL Server源(mdf、ldf、ndf),因为这些源位于Fortress(请参见

  • 问题内容: 通常,docker容器使用 root 用户运行。我想使用其他用户,使用docker的USER指令没问题。但是该用户应该能够在容器内使用 sudo 。该命令丢失。 这是用于此目的的简单Dockerfile: 运行此容器,我以用户’docker’登录。当我尝试使用sudo时,找不到命令。所以我尝试使用以下方法在Dockerfile中安装 sudo 软件包 这导致 无法找到包sudo 问题答

  • 问题内容: 似乎在容器中没有“ acl”的情况下挂载了文件系统,因此“ setfacl”将不起作用。而且它也不会让我重新安装它,甚至无法运行’df -h’。 我需要setfacl,因为我以root身份拥有我网站上的所有文件,并且授予Web服务器用户仅对几个目录(如缓存,日志等)的写权限。 我能做什么? 问题答案: 好消息是Docker支持ACL。 在早期版本中,Docker使用了一个不支持它们的名

  • 通常,docker容器使用用户root运行。我想使用一个不同的用户,这是没有问题的使用Docker的用户指令。但该用户应该能够在容器内使用sudo。缺少此命令。 下面是一个用于此目的的简单Dockerfile: 运行这个容器时,我使用用户'docker'登录。当我尝试使用sudo时,找不到该命令。所以我尝试在我的Dockerfile中安装sudo包,使用 这将导致无法定位包sudo

  • 问题内容: 我创建了一个活动,在其中将一些记录插入到mysql数据库中。我声明了一个名为的全局变量。当我尝试方法内部的变量时,工作正常,但是当我尝试方法外部时,返回。我还需要在方法之外使用此变量。该怎么办?这是我的代码: 谢谢! 问题答案: 我知道了。大约一年后,我回答了这个问题,因为我看到这个帖子有几百位访客。希望我的回答将帮助其他功能访问者从onResponse方法获取数据。这是代码: 这是我

  • 我注意到XCode中的UI组件:。 根据提供的描述,我想利用它在几个不同的屏幕上显示我的应用程序的可重用组件。我一直在网上寻找一个基本的教程或一些留档,但我没有找到任何有用的东西。 请问有人能建议如何把这个连接起来并利用它吗?目前,容器视图似乎没有调整大小,这是有问题的。关于如何启用此功能的任何提示也将不胜感激。 干杯