多数据源场景下如何获取指定的EntityManager?
问题解决步骤
1. 先解决实体类识别问题
报错“Not an entity: class com.activiti.entities.alfresco.TClaimModel”说明你的TClaimModel没被JPA识别为实体,先检查这几点:
- 类上是否加了
@Entity注解,包路径是否正确; - 实体类是否在Spring的组件扫描范围内(Spring Boot项目),或者在
persistence.xml的<class>标签里声明过; - 类必须是
public修饰,且有无参构造方法(JPA强制要求)。
2. 获取指定数据库的EntityManager
因为项目配置了两个数据库,Spring会生成两个EntityManager实例,得明确指定要注入的那个:
方法一:用@PersistenceContext指定持久化单元名称
多数据源配置时,每个数据源对应一个持久化单元,注入时指定unitName即可:
@PersistenceContext(unitName = "alfrescoPersistenceUnit") // 替换成你的持久化单元名称 private EntityManager entityManager;
这里的unitName要和你配置LocalContainerEntityManagerFactoryBean时设置的persistenceUnitName一致。
方法二:@Autowired结合@Qualifier指定bean名称
Spring Boot多数据源配置下,每个EntityManager bean有对应名称,用@Qualifier精准指定:
@Autowired @Qualifier("alfrescoEntityManager") // 替换成目标EntityManager的bean名称 private EntityManager entityManager;
bean名称一般是你配置LocalContainerEntityManagerFactoryBean时的方法名,或者手动设置的beanName。
方法三:通过EntityManagerFactory创建EntityManager
虽然EntityManagerFactory没有createQuery,但它可以生成EntityManager实例,先注入指定的工厂类再创建:
@Autowired @Qualifier("alfrescoEntityManagerFactory") private EntityManagerFactory entityManagerFactory; // 使用时创建EntityManager EntityManager entityManager = entityManagerFactory.createEntityManager();
注意:这种方式创建的EntityManager需要手动关闭(用完调用entityManager.close()),如果是Spring管理的事务场景,优先用前两种方法让Spring托管生命周期。
3. 动态过滤代码优化提示
解决EntityManager问题后,用Criteria API实现动态查询时,70个字段逐个判断太繁琐,可以用反射遍历实体字段自动生成查询条件,示例框架如下:
public List<TClaimModel> dynamicFilter(TClaimModel filter) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<TClaimModel> cq = cb.createQuery(TClaimModel.class); Root<TClaimModel> root = cq.from(TClaimModel.class); List<Predicate> predicates = new ArrayList<>(); // 反射遍历字段,自动添加非空条件 for (Field field : TClaimModel.class.getDeclaredFields()) { field.setAccessible(true); try { Object value = field.get(filter); if (value != null) { if (value instanceof String) { predicates.add(cb.like(root.get(field.getName()), "%" + value + "%")); } else { predicates.add(cb.equal(root.get(field.getName()), value)); } } } catch (IllegalAccessException e) { // 处理异常 } } cq.where(cb.and(predicates.toArray(new Predicate[0]))); return entityManager.createQuery(cq).getResultList(); }
内容的提问来源于stack exchange,提问作者WereElf
相关产品推荐
相关产品推荐

