Spring Boot应用启动失败:找不到entityManagerFactory Bean求助
entityManagerFactory Bean 启动Spring Boot Todo项目时遇到错误,提示找不到名为entityManagerFactory的Bean。
错误信息
APPLICATION FAILED TO START
Description:
Parameter 0 of constructor in com.todo.demo.service.TaskService required a bean named 'entityManagerFactory' that could not be found.
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.
相关代码
实体类Task
package com.todo.demo; import java.time.LocalDate; import jakarta.persistence.*; @Entity @Table(name = "tasks") /** * @Author Noah Rouse * @email: noahrouse36@gmail.com * @description: this class is designed to store and represent tasks in a todo list */ public class Task { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column private long id; @Column(name = "description", nullable = false) private String description; @Column(name = "completed") private boolean completed; @Column(name = "priority") private String priority; @Column(name = "due_date") private LocalDate dueDate; @Column(name = "created") private LocalDate created; @Column(name = "last_updated") private LocalDate lastUpdated; public Task () {} public Task (final Long id, final String description, final String priority, final LocalDate dueDate) { this.id = id; this.completed = false; this.description = description; this.priority = priority; this.dueDate = dueDate; this.created = LocalDate.now(); this.lastUpdated = created; } /** * @return task id */ public long id () { return this.id; } /** * @return description */ public String description () { return this.description; } /** * set task description to new description and changes last updated value * @return updated description */ public String description (final String description) { this.description = description; this.lastUpdated = LocalDate.now(); return this.description; } /** * @return if the task is completed */ public boolean completed () { return this.completed; } /** * Set completed to true or false * @return updated completed status */ public boolean completed (final boolean completed) { this.completed = completed; this.lastUpdated = LocalDate.now(); return this.completed; } /** * @return priority of task */ public String priority () { return this.priority; } /** * sets task to new priority * @return new priority */ public String priority (final String priority) { this.priority = priority; this.lastUpdated = LocalDate.now(); return this.priority; } /** * @return current task due date */ public LocalDate dueDate () { return this.dueDate; } /** * change due date to new local date * @return new due date */ public LocalDate dueDate (final LocalDate dueDate) { this.dueDate = dueDate; this.lastUpdated = LocalDate.now(); return this.dueDate; } /** * @return when the task was last updated */ public LocalDate lastUpdated () { return this.lastUpdated; } }
服务类TaskService
package com.todo.demo.service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.todo.demo.Task; import com.todo.demo.repository.TaskRepository; import java.time.LocalDate; import java.util.Optional; @Service @Transactional public class TaskService { public class TaskNotFoundException extends Exception { } private final TaskRepository taskRepos; public TaskService (final TaskRepository taskRepository) { taskRepos = taskRepository; } public void updateTaskDescription (final long taskId, final String description) throws TaskNotFoundException { final Optional<Task> potentialTask = taskRepos.findById(taskId); if (potentialTask.isPresent()) { final Task task = potentialTask.get(); task.description(description); taskRepos.save(task); } else { throw new TaskNotFoundException(); } } public void updateTaskCompletion (final long taskId, final boolean completed) throws TaskNotFoundException { final Optional<Task> potentialTask = taskRepos.findById(taskId); if (potentialTask.isPresent()) { final Task task = potentialTask.get(); task.completed(completed); taskRepos.save(task); } else { throw new TaskNotFoundException(); } } public void updateTaskPriority (final long taskId, final String priority) throws TaskNotFoundException { final Optional<Task> potentialTask = taskRepos.findById(taskId); if (potentialTask.isPresent()) { final Task task = potentialTask.get(); task.priority(priority); taskRepos.save(task); } else { throw new TaskNotFoundException(); } } public void updateTaskDueDate (final long taskId, final LocalDate dueDate) throws TaskNotFoundException { final Optional<Task> potentialTask = taskRepos.findById(taskId); if (potentialTask.isPresent()) { final Task task = potentialTask.get(); task.dueDate(dueDate); taskRepos.save(task); } else { throw new TaskNotFoundException(); } } }
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.todo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <url/> <licenses> <license/> </licenses> <developers> <developer/> </developers> <scm> <connection/> <developerConnection/> <tag/> <url/> </scm> <properties> <java.version>21</java.version> </properties> <dependencies> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.1.214</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>3.3.5</version> </dependency> <dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties文件
spring.application.name=demo spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.h2.console.enabled=true
问题原因及解决方案
原因
手动引入了spring-data-jpa和jakarta.persistence-api零散依赖,但未使用Spring Boot官方的spring-boot-starter-data-jpa。该starter会自动配置entityManagerFactory、EntityManager等核心JPA Bean,零散依赖会导致自动配置逻辑失效,缺少必要Bean。另外h2依赖未设置runtime scope,不符合Spring Boot最佳实践。
解决步骤
替换零散JPA依赖为Spring Boot JPA Starter
删除pom.xml中以下依赖:<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>3.3.5</version> </dependency> <dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.2.0</version> </dependency>添加官方JPA Starter:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>调整H2依赖的Scope
修改h2依赖,添加runtimescope:<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency>确认主启动类包扫描范围
确保主启动类(如DemoApplication)位于com.todo.demo包下,或添加@SpringBootApplication(scanBasePackages = "com.todo.demo")注解,保证能扫描到Repository、Service等组件。验证TaskRepository配置
确保TaskRepository接口继承JpaRepository<Task, Long>,Spring Boot会自动识别该接口并创建Bean。
完成以上修改后,执行mvn clean install重新构建项目,启动后entityManagerFactory Bean会被自动配置,报错即可解决。
内容的提问来源于stack exchange,提问作者Noah Rouse

