Spring Boot多模块下@Entity非托管类型问题求助
求助:@Entity被识别为非托管类型的排查方案
我一整天都在排查问题,查了大量资料,改了很多地方,但完全没进展。我有个数据库模块,里面有标注@Entity的Company类,还有对应的Repository和服务类。一开始这些类在子包里,我试过把它们移到同一个包,甚至把所有代码从模块移到主应用里,问题还是没解决。逐字检查过代码,没发现拼写或大小写错误。附上相关代码,日志太长超过字符限制,求帮忙排查原因。
实体类代码
@NoArgsConstructor @AllArgsConstructor @Getter @ToString @Entity @Table(name = "company") public class Company { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "company_id", nullable = false) private long id; @Column(name = "company_name", nullable = false) private String name; @Column(name = "addr1") private String adress1; @Column(name = "addr2") private String adress2; @Column(name = "addr3") private String adress3; @Column(name = "addr4") private String adress4; @Column(name = "postcode") private String postcode; }
Repository代码
@Repository public interface CompanyRepository extends JpaRepository<Company, Long> { List<Company> findByName(String companyName); @Query("SELECT c FROM Company c WHERE LOWER(c.name) LIKE LOWER(concat('%', :name,'%'))") List<Company> findByNameLike(@Param("name") String name); }
服务类代码
@Service public class DatabaseService { private final CompanyRepository companyRepository; @Autowired public DatabaseService(CompanyRepository companyRepository) { this.companyRepository = companyRepository; } public List<Company> findByName(String companyName) { return companyRepository.findByName(companyName); } public List<Company> findByNameLike(String companyName) { return companyRepository.findByNameLike(companyName); } }
数据库模块Gradle配置
plugins { java idea id("org.springframework.boot") version "3.2.4" id("io.spring.dependency-management") version "1.1.4" } group = "co.uk.myapp" version = "0.0.1-SNAPSHOT" val lombokVersion = "1.18.30" repositories { mavenCentral() } dependencies { compileOnly("org.projectlombok:lombok:$lombokVersion") annotationProcessor("org.projectlombok:lombok:$lombokVersion") implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation( "org.postgresql:postgresql:42.7.2") implementation( "com.zaxxer:HikariCP:5.1.0") testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } tasks.test { useJUnitPlatform() }
主项目Gradle配置
dependencies { implementation(project(":database")) compileOnly("org.projectlombok:lombok:$lombokVersion") annotationProcessor("org.projectlombok:lombok:$lombokVersion") implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-data-rest") implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.springframework.session:spring-session-core") developmentOnly("org.springframework.boot:spring-boot-devtools") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("io.projectreactor:reactor-test") }
application.yml配置
spring: application: name: "Management App" main: allow-bean-definition-overriding: true thymeleaf: cache: false datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://localhost:5000/management username: user_man password: statement-cache-size: 250 statement-cache-sql-limit: 2048 hikari: pool-name: MyHikariPool connection-timeout: 30000 maximum-pool-size: 10 minimum-idle: 5 idle-timeout: 600000 max-lifetime: 1800000
主类代码
@SpringBootApplication(scanBasePackages = {"co.uk.training", "co.uk.training.management" }) @EnableJpaRepositories(basePackageClasses = {CompanyRepository.class}) @EntityScan(basePackages = {"co.uk.training.database.entity"}) public class TrainingApplication { public static void main(String[] args) { SpringApplication.run(TrainingApplication.class, args); } }
排查要点及解决方案
1. 包路径不匹配
- 检查
@EntityScan指定的co.uk.training.database.entity是否与Company类的实际包完全一致。从数据库模块的group是co.uk.myapp来看,Company类的包大概率是co.uk.myapp.database.entity,而非co.uk.training.database.entity,这会导致实体类无法被扫描到。 - 建议改用
@EntityScan(basePackageClasses = {Company.class}),直接指定实体类字节码,避免字符串路径拼写错误。
2. Lombok构造方法访问权限问题
- JPA要求实体类必须有公开的无参构造方法,当前
@NoArgsConstructor默认生成private的无参构造,部分JPA实现无法识别。修改为:@NoArgsConstructor(access = AccessLevel.PUBLIC) - 可以通过查看编译后的class文件确认构造方法是否正确生成,或者临时去掉Lombok,手动编写无参构造测试。
3. 多模块JPA依赖重复
- 主项目和数据库模块都引入了
spring-boot-starter-data-jpa,可能导致依赖冲突或重复初始化。建议只在数据库模块保留该依赖,主项目依赖数据库模块即可,删除主项目Gradle中的implementation("org.springframework.boot:spring-boot-starter-data-jpa")。
4. YAML配置缩进错误
- 当前application.yml中
thymeleaf和datasource的配置存在缩进错误,导致数据源配置不生效,JPA无法初始化实体。修正后的正确格式:spring: application: name: "Management App" main: allow-bean-definition-overriding: true thymeleaf: cache: false datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://localhost:5000/management username: user_man password: statement-cache-size: 250 statement-cache-sql-limit: 2048 hikari: pool-name: MyHikariPool connection-timeout: 30000 maximum-pool-size: 10 minimum-idle: 5 idle-timeout: 600000 max-lifetime: 1800000
5. 实体ID类型不匹配
- Company类的id是基本类型
long,而Repository泛型是包装类型Long,虽然多数情况能兼容,但部分场景下可能导致类型识别异常。将id改为包装类型:@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "company_id", nullable = false) private Long id;
6. 数据库模块Spring Boot插件配置问题
- 数据库模块作为子模块,不需要使用
org.springframework.boot插件(该插件会将子模块打包为独立Spring Boot应用),去掉数据库模块Gradle中的id("org.springframework.boot") version "3.2.4",仅保留io.spring.dependency-management插件管理依赖即可。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

