org.springframework.dao.InvalidDataAccessApiUsageException:org.hibernate.query.sqm.UnknownEntityException:无法解析根实体“OrderInfo”

问题描述 投票:0回答:1

我在 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”注解是否正确应用。

spring-boot hibernate jpa querydsl
1个回答
0
投票

您的辅助数据源无法工作的原因,第一个数据源是在 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
    }
}

毕竟,再试一次。

© www.soinside.com 2019 - 2024. All rights reserved.