【问题标题】:How to work with spring4+spring-data-jpa(hibernateJpaVendorAdapter)+multidatasource+one entityManager+jpaRepository?如何使用 spring4+spring-data-jpa(hibernateJpaVendorAdapter)+multidatasource+one entityManager+jpaRepository?
【发布时间】:2017-12-12 19:01:22
【问题描述】:

我遇到一个项目,有两个数据库,但这些数据库中的数据结构不同,涉及多数据源中的事务管理。

另外,我想使用JpaRepository,它只是在一些扩展JpaRepository的接口上添加@Repository注解,重点关注sql语句。例如:

@Scope(value="prototype")
@Repository
public interface UserRepository extends JpaRepository<User, Integer>,
 JpaSpecificationExecutor<User> {
    @Query(value="select * from users",nativeQuery=true)
    public List<User>  getAll();

    @Query(value="select * from users where email=binary ?1 or   phone_number=?1",nativeQuery=true)
    public User findUserByEmailOrPhone(String name);

    public User save(User user);

    @Modifying
    @Query("Update User u set u.lastLoginTime=?2,u.mac=?3,u.lastIp=?4 where u.id=?1")
    public int updateLast_login(Integer id,Date last_loginTime,String mac,
          String last_ip);
  }

关于事务管理,我想继续使用@Transctional注解,但这涉及到两个mysql数据库中sql语句的执行。

根据我对一个数据源的经验,我想只有一个entityManagerFactory来管理两个数据源中的不同实体类。

但是如何配置JpaRepository接口和数据源的映射,告诉entityManagerFactory数据源和实体类的映射呢?

这是我想要完成上述功能的示例。

// this entity data  is restored in A databse's Atab table
@Table
@Entity
public class A{
   private String A_item1;
   private Integer A_item2;
   private Long A_item3;
   public A(){
      super();
   }
}
 // this entity data is restored in B databse's Btab table
 @Table
 @Entity
 public class B{
     private String B_item1;
     private Integer B_item2;
     private Long B_item3;
     public B(){
         super();
     }
 }

 @Repository
 public interface A_Repository extends JpaRepository<A, Integer>,
 JpaSpecificationExecutor<A>{

      public A save(A a);

      @Modifying
      @Query(value="update Atab  set a_item1=?1 where a_item2=?2",nativeQuery=true)
      public A update(String a_item1,int a_item2 );

      public A update(A a);
 }

 @Repository
 public interface B_Repository extends JpaRepository<B, Integer>,
 JpaSpecificationExecutor<B>{

      public B save(B a);

      @Modifying
      @Query(value="update Btab  set b_item1=?1 where b_item2=?2",nativeQuery=true)
      public B update(String b_item1,int b_item2 );

      public B update(B b);
 }

 @service
 public class A_B_Service{

    @Autowired
    A_Repository a_Repos;

    @Autowired
    B_Repository b_Repos;

    @Transactional(rollbackFor=Exception.class)
    public void synchronous_save_AandB(A a,B b){
          a_Repos.save(a);
          b_Repos.save(b);

    }

    @Transactional(rollbackFor=Exception.class)
    public void synchronous_update_AandB(A a,B b){
          a_Repos.update(a);
          b_Repos.update(b);
    }

    @Transactional(rollbackFor=Exception.class)
    public void synchronous_update_AandB(String a_item1,int a_item2,String b_item1,int b_item2){
          a_Repos.update( a_item1,a_item2);
          b_Repos.update(b_item1,b_item2);
    }
 }  

【问题讨论】:

    标签: spring hibernate jpa spring-data


    【解决方案1】:

    你不能,除非每个数据库基本上都是独立的。

    每个实体都属于一个或多个JPARepository(是的,您可以根据需要为每个实体拥有多个存储库)。

    每个JPARepository 属于一个EntityManager (如果使用Hibernate 和Spring,它基于您的扫描包)您可能有多个EntityManagers 扫描同一个包,但我认为您会有并发和如果这样做,数据覆盖问题。

    每个EntityManager 只有一个数据源。 (我知道没有多数据源EntityManagers)

    每个事务可能有多个EntityManagers。它不能是您的标准@Transactional,您必须配置一个JTATransactionalManager 来代替标准@,但这应该不会太难。请注意,每个事务中最多可以有 1 个非 XA 数据源。

    另请注意,我所知道的任何EntityManager 都不支持跨数据源/EntityManagers 的 SQL 或 JPQL。

    【讨论】:

    • ,谢谢!根据您的评论,我已经搜索了一些关于JTATransactionalManager的问题,但它没有集成配置和使用。我的webservice机器是tomcat7,我需要找到一个新的webservice容器?我是JTATransactionalManager 的新手,你能找到一些关于我的情况的例子吗?
    【解决方案2】:

    您需要提供一些额外的配置选项来完成此操作

    @EnableJpaRepositories(
      basePackages = { "com.yourappliction.feature1.repositories" },
      entityManagerFactoryRef = "entityManagerFeature1",
      transactionManagerRef = "transactionManagerFeature1"
    )
    
    @EnableJpaRepositories(
      basePackages = { "com.yourapplication.feature2.repositories" },
      entityManagerFactoryRef = "entityManagerFactoryFeature2",
      transactionManagerRef = "transactionManagerFeature2"
    )
    

    这意味着您需要为EntityManagerFactoryTransactionManager 配置 2 个 bean。

    feature1 中的 JpaRepository 接口将使用这些特定的 bean,而 feature2 将使用其他配置的 bean。

    没有办法通过单个EntityManagerFactory 来完成此操作,因为工厂专门用于数据源。过去开发了一些自定义框架来支持这一点,但它不是 JPA 的原生特性。

    【讨论】:

      猜你喜欢
      • 2022-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 2017-08-17
      • 2011-01-26
      • 2016-01-23
      • 2016-12-10
      相关资源
      最近更新 更多