Spring Boot自定义JPA @Entity注解实现多数据源切换遇异常
解决Spring Boot自定义注解替代@Entity时的"Not a managed type"异常
核心问题
JPA的实体扫描器默认仅识别@Entity注解标记的类,自定义的@MyOwn注解未被纳入扫描范围,因此抛出Not a managed type异常。
解决步骤
1. 完善自定义@MyOwn注解的元注解
让@MyOwn同时继承@Entity和@Document的元注解特性,确保两种数据库都能识别该注解:
import jakarta.persistence.Entity; import org.springframework.data.mongodb.core.mapping.Document; import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Document // 保留MongoDB映射支持 @Entity // 添加JPA实体标记 @Inherited // 增强注解兼容性(可选) public @interface MyOwn { // 可复用原注解的属性,比如对应@Entity的name或@Document的collection String name() default ""; String collection() default ""; }
2. 显式配置JPA扫描@MyOwn注解
如果元注解方式不生效,手动配置JPA实体工厂扫描自定义注解:
import jakarta.persistence.EntityManagerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import javax.sql.DataSource; @Configuration public class JpaConfig { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); // 指定实体类所在包路径 em.setPackagesToScan("com.mt.mtamp.employee.entity"); em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); // 关键:配置Hibernate扫描自定义@MyOwn注解作为实体标记 em.getJpaPropertyMap().put("hibernate.ejb.entity_scanning.annotation", "com.mt.mtamp.employee.annotation.MyOwn"); return em; } }
3. 实现数据库动态切换(可选)
通过Spring的@Conditional注解,根据配置自动激活JPA或MongoDB的配置:
- 定义判断数据库类型的Condition类:
import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class JpaCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return "jpa".equalsIgnoreCase(context.getEnvironment().getProperty("spring.database.type")); } } public class MongoCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return "mongo".equalsIgnoreCase(context.getEnvironment().getProperty("spring.database.type")); } }
- 分别创建JPA和MongoDB的配置类:
// JPA配置类 @Configuration @Conditional(JpaCondition.class) @EnableJpaRepositories(basePackages = "com.mt.mtamp.employee.repository.jpa") public class JpaDatabaseConfig { // 包含上述的EntityManagerFactoryBean配置 } // MongoDB配置类 @Configuration @Conditional(MongoCondition.class) @EnableMongoRepositories(basePackages = "com.mt.mtamp.employee.repository.mongo") public class MongoDatabaseConfig { // MongoDB相关配置(如MongoTemplate等) }
- 在
application.properties中配置切换:
spring.database.type=jpa # 或mongo
4. 验证实体类的JPA注解完整性
确保实体类上的字段级JPA注解(如@Id、@Column等)保留正确,示例:
@MyOwn(name = "employee") public class Employee { @Id private Long id; @Column(name = "emp_name") private String name; // 其他字段、getter/setter }
内容的提问来源于stack exchange,提问作者bharathi
相关产品推荐
相关产品推荐

