简体   繁体   English

Spring-boot:不能使用持久性

[英]Spring-boot: cannot use persistence

I am days into this, and - although I am learning a lot - starting to despair. 我很喜欢这个,而且 - 虽然我学到了很多 - 但开始绝望了。

I have tried all the suggestions on this excellent question: 我已经尝试过关于这个优秀问题的所有建议:

No Persistence provider for EntityManager named 没有为EntityManager命名的持久性提供程序

I had this working at one point using the ubiquitous HibernateUtil class, but was told to move to a plain JPA style here: 我曾经使用无处不在的HibernateUtil类在某一点上工作,但被告知要转到普通的JPA样式:

Spring RESTful controller method improvement suggestions Spring RESTful控制器方法改进建议

Unfortunately, I could not get the bean injection to work properly in spring-boot. 不幸的是,我无法让bean注入在spring-boot中正常工作。 Here is my attempt: 这是我的尝试:

Spring JPA (Hibernate) No qualifying bean of type: javax.persistence.EntityManagerFactory Spring JPA(Hibernate)没有类型的限定bean:javax.persistence.EntityManagerFactory

After much work down that path I ended up with a null entity manager. 经过这条路径的大量工作后,我最终得到了一个空实体管理器。 I found this and began to think it could not work: 我发现了这一点并开始认为它不起作用:

Using JPA2 in Tomcat 6: @PersitenceContext doesn't work, EntityManager is null 在Tomcat 6中使用JPA2:@PersitenceContext不起作用,EntityManager为null

It seems to me like the EntityManagerFactory absolutely should be a bean in whatever context spring-boot creates, but ... whatever. 在我看来,EntityManagerFactory绝对应该是spring-boot创建的任何上下文中的bean,但是......无论如何。 I would think that at least this would work: 我认为至少这会起作用:

Application launch: 申请发布:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Controller: 控制器:

@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;
    }
}

DAO: DAO:

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: /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>

And it doesn't work: 它不起作用:

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)

--- Added Info --- ---添加信息---

POM: 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>

spring boot does not read persistence.xml file by default, see the document here spring boot默认不读取persistence.xml文件,请参阅此处的文档

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html

so if you want to keep using persistence.xml file just add below code into your AppConfig class 因此,如果您想继续使用persistence.xml文件,只需在AppConfig类中添加以下代码即可

@Bean
public LocalEntityManagerFactoryBean entityManagerFactory(){
     LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
    factoryBean.setPersistenceUnitName("cpJpaPu");
    return factoryBean;
}

persistence.xml应位于META-INF目录中

/src/main/resources/META-INF/persistence.xml

There are some features of JPA that only work in XML configuration unfortunately, but I can't see anything like that in yours. 不幸的是,JPA的一些功能只能在XML配置中工作,但我在你的内容中看不到类似的东西。 I don't think persistence.xml is loaded by default, so probably that's the issue. 我不认为默认情况下会加载persistence.xml ,所以可能就是这个问题。 So why don't you go with the flow and use Java and application.properties to configure the entity manager? 那么为什么不选择流程并使用Java和application.properties来配置实体管理器呢? The JPA sample from Spring Boot has everything you need to get started. Spring BootJPA示例提供了入门所需的一切。 It uses Spring Data JPA, whereas your code is only using the JPA APIs, but you can easily strip back to that level by just removing the Spring Data dependencies in the sample. 它使用Spring Data JPA,而您的代码仅使用JPA API,但您可以通过删除示例中的Spring Data依赖项轻松地回退到该级别。

Recent Spring Boot snapshots have a feature that lets you create your own LocalEntityManagerFactoryBean so that you can add a custom XML configuration, but up to M7 you would have to do all the JPA configuration manually once you needed a custom EntityManager . 最近的Spring Boot快照有一个功能,允许您创建自己的LocalEntityManagerFactoryBean以便您可以添加自定义XML配置,但是在M7之后,您需要在需要自定义EntityManager手动执行所有JPA配置。

NB you aren't really using dependency injection very effectively in your controller - why wouldn't you just inject the UserDao ? 注意,你并没有真正在你的控制器中有效地使用依赖注入 - 你为什么不注入UserDao

This question was answered with a much better architecture over here: 这个问题在这里得到了更好的架构回答:

Spring JPA (Hibernate) No qualifying bean of type: javax.persistence.EntityManagerFactory Spring JPA(Hibernate)没有类型的限定bean:javax.persistence.EntityManagerFactory

I resolved this issue after deleted all hibernate-core folders under below directory: .m2\\repository\\org\\hibernate\\hibernate-core 我删除了以下目录下的所有hibernate-core文件夹后解决了这个问题:.m2 \\ repository \\ org \\ hibernate \\ hibernate-core

and rebuilt my projects. 并重建了我的项目。

Now, it works fine under Spring Boot 2.0.4.RELEASE. 现在,它在Spring Boot 2.0.4.RELEASE下工作正常。 And I'm sure that it loads the main/resources/META-INF/persistence.xml without injecting LocalEntityManagerFactoryBean Bean. 我确信它在不注入LocalEntityManagerFactoryBean Bean的情况下加载了main / resources / META-INF / persistence.xml。

Before I delete them, there are 4 versions of hibernate-core in the above folder. 在删除它们之前,上面的文件夹中有4个版本的hibernate-core。 They are "4.3.6"/"5.0.12"/"5.2.17"/"5.3.4". 它们是“4.3.6”/“5.0.12”/“5.2.17”/“5.3.4”。

After I deleted them, there are "5.0.12"/"5.2.17"/"5.3.4" after rebuilt my projects. 删除后,重建项目后有“5.0.12”/“5.2.17”/“5.3.4”。

And when I dig into this issue, I found that the "hibernate-core-5.2.17.Final.jar" in previous "5.2.17" folder is bigger than the normal and it has no "hibernate-core-5.2.17.Final.jar.sha1". 当我深入研究这个问题时,我发现之前“5.2.17”文件夹中的“hibernate-core-5.2.17.Final.jar”比正常文件大,并且它没有“hibernate-core-5.2.17” .Final.jar.sha1" 。

So, it may caused by poor network or poor mirror. 因此,它可能是由于网络不良或镜像不佳造成的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM