我遇到的项目有两个数据库,但这些数据库中的数据结构不同,涉及多数据源中的事务管理。
旁边,我想使用JpaRepository
,它只是将@Repository
注释添加到扩展JpaRepository
的某个接口,重点关注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);
}
}
答案 0 :(得分:0)
除非每个数据库基本上都是自包含的,否则不能。
每个实体属于一个或多个JPARepository
(是的,如果需要,您可以为每个实体拥有多个存储库)。
每个JPARepository
属于一个EntityManager
(如果使用Hibernate和Spring,它基于您的扫描包)您可能有多个EntityManager
扫描相同的包,但如果你这样做,我认为你会有并发和数据覆盖问题。
每个EntityManager
只有一个数据源。 (没有多数据源EntityManager
我知道)
每笔交易可能有多个EntityManager
。它不能成为您的标准@Transactional
,您必须配置JTATransactionalManager
代替标准版本,但这不应该太难。请注意,每个事务中最多只能有一个非XA数据源。
另请注意,我所知道的任何EntityManager
都不支持跨数据源/ EntityManager
的SQL或JPQL。
答案 1 :(得分:0)
您需要提供一些其他配置选项才能完成此操作
@EnableJpaRepositories(
basePackages = { "com.yourappliction.feature1.repositories" },
entityManagerFactoryRef = "entityManagerFeature1",
transactionManagerRef = "transactionManagerFeature1"
)
@EnableJpaRepositories(
basePackages = { "com.yourapplication.feature2.repositories" },
entityManagerFactoryRef = "entityManagerFactoryFeature2",
transactionManagerRef = "transactionManagerFeature2"
)
这意味着您需要为EntityManagerFactory
和TransactionManager
配置2个bean。
feature1 中的JpaRepository
接口将使用这些特定的bean,而 feature2 将使用其他配置的bean。
单个EntityManagerFactory
无法实现此目的,因为工厂专门用于数据源。过去已经开发了一些自定义框架来支持这一点,但它不是JPA的本机功能。