java - Spring/Hibernate 多个数据源之间具有外键
问题描述
假设我有两个表,在不同的模式中。因此,我为每个数据源创建了一个实体和事务管理器:
@Configuration
@EnableJpaRepositories(
basePackages = "com.(omitted).endpoints.all.endpoint.crm",
entityManagerFactoryRef = "crmEntityManager",
transactionManagerRef = "crmTransactionManager"
)
public class PersistenceCrmConfig {
@Autowired
private Environment environment;
public PersistenceCrmConfig() {
super();
}
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean crmEntityManager() {
final LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
bean.setDataSource(crmDataSource());
bean.setPackagesToScan("com.(omitted).data.all.model.crm");
...
}
@Primary
@Bean
public PlatformTransactionManager crmTransactionManager() {
...
}
@Primary
@Bean
public DataSource crmDataSource() {
...
}
}
@Configuration
@EnableJpaRepositories(
basePackages = "com.(omitted).endpoints.all.endpoint.user",
entityManagerFactoryRef = "userEntityManager",
transactionManagerRef = "userTransactionManager"
)
public class PersistenceUserConfig {
@Autowired
private Environment environment;
public PersistenceUserConfig() {
super();
}
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean userEntityManager() {
final LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
bean.setDataSource(userDataSource());
bean.setPackagesToScan("com.(omitted).data.all.model.user");
...
}
@Primary
@Bean
public PlatformTransactionManager userTransactionManager() {
...
}
@Primary
@Bean
public DataSource userDataSource() {
...
}
}
在user
数据源(模式)中,我有一个实体 ,它与数据源(模式)中的实体User
有一对一的映射。Person
crm
@JoinColumn(name = "person_id", nullable = false)
@OneToOne(fetch = FetchType.LAZY)
private Person person;
这会导致异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userEntityManager' defined in class path resource [com/(omitted)/endpoints/all/spring/PersistenceUserConfig.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.(omitted).data.all.model.user.User.person references an unknown entity: com.(omitted).data.all.model.crm.Person
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) ~[spring-context-5.3.8.jar:5.3.8]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) ~[spring-context-5.3.8.jar:5.3.8]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.8.jar:5.3.8]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.1.jar:2.5.1]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.1.jar:2.5.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.1.jar:2.5.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.1.jar:2.5.1]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:144) ~[spring-boot-2.5.1.jar:2.5.1]
at com.(omitted).endpoints.all.Application.main(Application.java:11) ~[classes/:na]
Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.(omitted).data.all.model.user.User.person references an unknown entity: com.(omitted).data.all.model.crm.Person
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:100) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1823) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1767) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1655) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:295) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.8.jar:5.3.8]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.8.jar:5.3.8]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.8.jar:5.3.8]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.8.jar:5.3.8]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.8.jar:5.3.8]
... 15 common frames omitted
我明白为什么我会收到这个错误。Spring 必须生成两个 Hibernate Session Factories,因此,两个彼此一无所知的实体列表。
如何使一对一映射起作用?
谢谢你。
解决方案
没有办法让它与两个 Hibernate Session Factories 一起工作。我也不建议尝试强制 Hibernate 为这种情况创建一个。
我看到的简单解决方法是在数据库方面。person
考虑在user
架构中创建表视图并将Person
实体映射到视图,而不是表。
这种方法不允许您person
使用您的更新表userEntityManager
(除非您使用的是 Oracle DB)。如果您需要在某些时候执行此操作,您可以使用您在表crmEntityManager
中找到相应person
的并更新它。
请记住,如果由于您提到的相同原因(不同的会话工厂)而必须同时更新两者person
并user
作为单个操作的一部分进行更新,则事务性可能会受到损害。
推荐阅读
- mysql - MySQL 将字母转换为数字(例如,'A' 转换为 1,'B' 转换为 2...)
- wordpress - 使用 flamingo 和联系表 7 中存储的数据并将其显示在结帐页面字段中
- c# - 如何在堆积条形图上显示平均计数而不是总数?
- java - 多个相同长度的模型同时迭代
- android - 如何使用 Image.memory() 或 MemoryImage() 缓存内存图像?
- terraform - .terraform.lock.hcl 是否应该包含在 .gitignore 文件中?
- reactjs - 无法使用 cytoscape.js 制作非常基本的有向图并做出反应
- c - 如何清除C中的字符串
- io - parquet row_group mapping metadata
- python - 尝试通过model.py将对象保存到数据库时出现Django AttributeError