我在 SpringBoot 3.0.5 中使用 Java 17 配置了 MultiDataSource。主数据源工作正常,但我遇到了辅助数据源的问题。
OrderRepository 接口中的 findAll() 方法工作正常,没有任何问题,但我在 OrderQueryDsl 的 getOrderInfo() 方法中不断收到错误。我已经尝试解决这个问题好几天了,但我就是不明白原因。请帮帮我。
@Configuration
@RequiredArgsConstructor
@EnableJpaRepositories(
basePackages = "com.demo.solution.invoice.repository.secondary",
entityManagerFactoryRef = "secondaryEntityManager",
transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryDataSourceConfiguration {
private final Environment env;
private final SecondaryDBPropertiesConfig secondaryDBPropertiesConfig;
@Bean
public LocalContainerEntityManagerFactoryBean secondaryEntityManager(){
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(secondaryDataSource());
em.setPackagesToScan("com.demo.solution.invoice.entity.secondary");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaPropertyMap(jpaProperties());
return em;
}
@Bean
public DataSource secondaryDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(secondaryDBPropertiesConfig.getJdbcUrl());
dataSource.setUsername(secondaryDBPropertiesConfig.getAdminID());
dataSource.setPassword(secondaryDBPropertiesConfig.getAdminPW());
return dataSource;
}
@Bean
public PlatformTransactionManager secondaryTransactionManager() {
JpaTransactionManager transactionManager= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(secondaryEntityManager().getObject());
return transactionManager;
}
private HashMap<String, String> jpaProperties(){
HashMap<String, String> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", env.getProperty("jpa.hibernate.ddl-auto"));
properties.put("hibernate.dialect", secondaryDBPropertiesConfig.getDialect());
//properties.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
properties.put("hibernate.show_sql", env.getProperty("jpa.hibernate.show_sql"));
properties.put("hibernate.format_sql", env.getProperty("jpa.hibernate.format_sql"));
return properties;
}
}
package com.demo.solution.invoice.entity.secondary;
@NoArgsConstructor
@Entity
@Table(name = "orders")
@Getter
@ToString
public class OrderInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "order_id")
private Integer orderId;
@Column(name = "order_no")
private String orderNo;
@Column(name = "created_time")
private LocalDateTime createdTime;
}
package com.demo.solution.invoice.repository.secondary;
@Repository
@RequiredArgsConstructor
public class OrderQueryDsl {
private final JPAQueryFactory queryFactory;
public List\<OrderInfo\> getOrderInfo(){
List\<OrderInfo\> orderInfos = queryFactory
.selectFrom(QOrderInfo.orderInfo)
.fetch(); // error
return orderInfos;
}
}
@Repository public interface OrderRepository extends JpaRepository\<OrderInfo, String\> { }
@SpringBootTest
@ActiveProfiles("local")
class OrderQueryDslTest {
@Autowired
OrderQueryDsl orderQueryDsl;
@Test
void getOrders() {
List<OrderInfo> orderInfos = orderQueryDsl.getOrderInfo(); // error
}
}
[完整堆栈跟踪]
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.query.sqm.UnknownEntityException: Could not resolve root entity 'OrderInfo'
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:234)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:702)
at com.demo.solution.invoice.repository.secondary.OrderQueryDsl$$SpringCGLIB$$0.getOrderInfo(\<generated\>)
at
我已尽我所能询问 ChatGPT,但它的答复仅限于建议诸如使用“@EntityScan”或检查“OrderInfo”类的包位置 (setPackagesToScan) 之类的事情。主要是确认“@Entity”注解是否正确应用。
您的辅助数据源无法工作的原因,第一个数据源是在 EntityManager 注入的。
enter code here
@Bean
public LocalContainerEntityManagerFactoryBean secondaryEntityManager(){
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(secondaryDataSource());
em.setPackagesToScan("com.demo.solution.invoice.entity.secondary");
**em.setPersistenceUnitName("secondaryEntityManager");** // add here
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaPropertyMap(jpaProperties());
return em;
}
在EntityManager设置PersistenceUnitName后,请制作配置文件。
@Configuration
public class JpaConfig {
@PersistenceContext(unitName = "firstEntityManager")
private EntityManager firstEntityManager;
@PersistenceContext(unitName = "secondaryEntityManager")
private EntityManager secondEntityManager;
@Bean
@Primary
@Qualifier("FirstQF")
JPAQueryFactory firstQueryFactory() {
return new JPAQueryFactory(firstEntityManager);
}
@Bean
@Qualifier("SecondQF")
JPAQueryFactory secondQueryFactory() {
return new JPAQueryFactory(secondEntityManager);
}
}
您必须创建与您使用的数据库一样多的 EntityManager 和 JPAQueryFactory。
package com.demo.solution.invoice.repository.secondary;
@Repository
public class OrderQueryDsl {
private final JPAQueryFactory queryFactory;
// add constructor
public OrderQueryDsl(@Qualifier("SecondQF") JPAQueryFactory queryFactory) {
this.queryFactory = queryFactory;
}
public List<OrderInfo> getOrderInfo() {
List<OrderInfo> orderInfos = queryFactory
.selectFrom(QOrderInfo.orderInfo)
.fetch(); // error
return orderInfos;
}
}
并使用构造函数注入和@Qualifier。
@SpringBootTest
@ActiveProfiles("local")
class OrderQueryDslTest {
@Autowired
OrderQueryDsl orderQueryDsl;
@Test
void getOrders() {
List<OrderInfo> orderInfos = orderQueryDsl.getOrderInfo(); // error
}
}
毕竟,再试一次。