Spring-boot:不能使用持久性
Posted
技术标签:
【中文标题】Spring-boot:不能使用持久性【英文标题】:Spring-boot: cannot use persistence 【发布时间】:2014-01-17 20:48:01 【问题描述】:我已经为此投入了好几天,并且 - 尽管我学到了很多东西 - 开始感到绝望。
我已经尝试了关于这个优秀问题的所有建议:
No Persistence provider for EntityManager named
我曾经使用无处不在的 HibernateUtil 类来完成这项工作,但在这里被告知要改用普通的 JPA 样式:
Spring RESTful controller method improvement suggestions
不幸的是,我无法让 bean 注入在 spring-boot 中正常工作。这是我的尝试:
Spring JPA (Hibernate) No qualifying bean of type: javax.persistence.EntityManagerFactory
在这条道路上经过大量工作后,我最终得到了一个空实体管理器。我发现了这个并开始认为它不起作用:
Using JPA2 in Tomcat 6: @PersitenceContext doesn't work, EntityManager is null
在我看来,EntityManagerFactory 在 spring-boot 创建的任何上下文中绝对应该是一个 bean,但是......无论如何。我认为至少这会起作用:
应用启动:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application
public static void main(String[] args)
SpringApplication.run(Application.class, args);
控制器:
@Controller
public class GetController
private static final String PERSISTENCE_UNIT_NAME = "cpJpaPu";
@RequestMapping(value = "/user", method = RequestMethod.GET)
public @ResponseBody User getUser(@RequestParam(value="id", required=true) int id)
User user = null;
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = emf.createEntityManager();
UserDAO userDao = new UserDAO();
userDao.setEntityManager(em);
user = userDao.load(id);
return user;
道:
public class UserDAO
public EntityManager entityManager;
public void setEntityManager(EntityManager entityManager)
this.entityManager = entityManager;
public EntityManager getEntityManager()
return entityManager;
public void insert(User user)
entityManager.persist(user);
public User load(int id)
return entityManager.find(User.class, id);
/src/main/resources/persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="cpJpaPu" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.mydomain.User</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.connection.username" value="user"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/mydb"/>
</properties>
</persistence-unit>
</persistence>
它不起作用:
javax.persistence.PersistenceException: No Persistence provider for EntityManager named cpJpaPu
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
com.mydomain.GetController.getUser(GetController.java:25)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:214)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:748)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:947)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:878)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:946)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:837)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:822)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
--- 添加信息 ---
POM:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mygroup</groupId>
<artifactId>myartifact</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>0.5.0.M6</version>
</parent>
<dependencies>
<!-- Spring framework -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<!-- Must override version or face stack traces -->
<version>4.3.0.Final</version>
</dependency>
<!-- Spring ORM, works with Hibernate -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<!-- Spring implementation of Jackson for RESTful JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- JDBC -->
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901.jdbc4</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- Prevent logging conflicts -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<properties>
<start-class>com.cloudfordev.controlpanel.Application</start-class>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</project>
【问题讨论】:
如果你使用default
作为持久化单元的名字会发生什么?
同样的问题@chrylis
/src/main/resources 在类路径中,对吗?我可以告诉你eclipse在构建jar时并没有排除它。
出于好奇,您为什么要手动创建 EMF 而不是像往常一样注入它?
@chrylis 我无法让注入工作...请参阅我关于 Spring EntityManager / EntityManagerFactory 的其他一些问题。我宁愿将 EMF 作为 bean,但是 Tomcat / Spring-boot 可以吗?我知道除非我在 Java-EE 环境中,否则 DI 注入可能不起作用
【参考方案1】:
spring boot默认不读取persistence.xml文件,请看这里的文档
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html
因此,如果您想继续使用 persistence.xml 文件,只需将以下代码添加到您的 AppConfig 类中
@Bean
public LocalEntityManagerFactoryBean entityManagerFactory()
LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName("cpJpaPu");
return factoryBean;
【讨论】:
【参考方案2】:persistence.xml 应该在 META-INF 目录中
/src/main/resources/META-INF/persistence.xml
【讨论】:
我试过了,还是不行,看这个帖子:***.com/questions/40399054/…【参考方案3】:不幸的是,JPA 的某些功能只能在 XML 配置中使用,但我在您的配置中看不到类似的东西。我认为默认情况下不会加载persistence.xml
,所以这可能就是问题所在。那么为什么不顺其自然,使用 Java 和 application.properties 来配置实体管理器呢? JPA sample from Spring Boot 拥有您入门所需的一切。它使用 Spring Data JPA,而您的代码仅使用 JPA API,但您只需删除示例中的 Spring Data 依赖项即可轻松剥离回该级别。
最近的 Spring Boot 快照具有一项功能,可让您创建自己的 LocalEntityManagerFactoryBean
,以便您可以添加自定义 XML 配置,但在 M7 之前,您必须在需要自定义 @987654324 时手动执行所有 JPA 配置@。
注意您并没有真正在控制器中非常有效地使用依赖注入 - 为什么不直接注入 UserDao
?
【讨论】:
【参考方案4】:这个问题在这里得到了一个更好的架构的回答:
Spring JPA (Hibernate) No qualifying bean of type: javax.persistence.EntityManagerFactory
【讨论】:
【参考方案5】:我在删除以下目录下的所有 hibernate-core 文件夹后解决了这个问题:.m2\repository\org\hibernate\hibernate-core
并重建我的项目。
现在,它在 Spring Boot 2.0.4.RELEASE 下运行良好。而且我确信它会加载 main/resources/META-INF/persistence.xml 而不注入 LocalEntityManagerFactoryBean Bean。
在我删除它们之前,上面的文件夹中有 4 个版本的 hibernate-core。它们是“4.3.6”/“5.0.12”/“5.2.17”/“5.3.4”。
我删除它们后,重建我的项目后有“5.0.12”/“5.2.17”/“5.3.4”。
当我深入研究这个问题时,我发现之前的“5.2.17”文件夹中的“hibernate-core-5.2.17.Final.jar”比正常文件夹大,并且没有“hibernate-core- 5.2.17.Final.jar.sha1"。
所以可能是网络不好或者镜像不好造成的。
【讨论】:
以上是关于Spring-boot:不能使用持久性的主要内容,如果未能解决你的问题,请参考以下文章
关于如何使用 jpa-repositiroies 在 Spring-Boot 上持久保存数据的指南/教程
Bootstrap 不能与 spring-boot 一起使用?