如何使用 spring4+spring-data-jpa(hibernateJpaVendorAdapter)+multidatasource+one entityManager+jpaReposit
Posted
技术标签:
【中文标题】如何使用 spring4+spring-data-jpa(hibernateJpaVendorAdapter)+multidatasource+one entityManager+jpaRepository?【英文标题】:How to work with 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);
【问题讨论】:
【参考方案1】:你不能,除非每个数据库基本上都是独立的。
每个实体都属于一个或多个JPARepository
(是的,您可以根据需要为每个实体拥有多个存储库)。
每个JPARepository
属于一个EntityManager
(如果使用Hibernate 和Spring,它基于您的扫描包)您可能有多个EntityManager
s 扫描同一个包,但我认为您会有并发和如果这样做,数据覆盖问题。
每个EntityManager
只有一个数据源。 (我知道没有多数据源EntityManager
s)
每个事务可能有多个EntityManager
s。它不能是您的标准@Transactional
,您必须配置一个JTATransactionalManager
来代替标准@,但这应该不会太难。请注意,每个事务中最多可以有 1 个非 XA 数据源。
另请注意,我所知道的任何EntityManager
都不支持跨数据源/EntityManager
s 的 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"
)
这意味着您需要为EntityManagerFactory
和TransactionManager
配置 2 个 bean。
feature1 中的 JpaRepository
接口将使用这些特定的 bean,而 feature2 将使用其他配置的 bean。
没有办法通过单个EntityManagerFactory
来完成此操作,因为工厂专门用于数据源。过去开发了一些自定义框架来支持这一点,但它不是 JPA 的原生特性。
【讨论】:
以上是关于如何使用 spring4+spring-data-jpa(hibernateJpaVendorAdapter)+multidatasource+one entityManager+jpaReposit的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring-data 中更改/定义 Mongodb 的默认数据库?
您如何保护 Spring Boot / Spring-Data Rest 以便用户只能访问他自己的实体
如何在 spring-data 2.0.x 中创建 RedisCacheManager
使用 Eclipse Scala IDE 中的 spring-data 注入测试 playframework 2.4