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
I had this working at one point using the ubiquitous HibernateUtil class, but was told to move to a plain JPA style here:
Spring RESTful controller method improvement suggestions
Unfortunately, I could not get the bean injection to work properly in spring-boot. Here is my attempt:
Spring JPA (Hibernate) No qualifying bean of type: 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
It seems to me like the EntityManagerFactory absolutely should be a bean in whatever context spring-boot creates, but ... whatever. 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:
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>
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:
<?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 will not search for or use a META-INF/persistence. xml by default. If you prefer to use a traditional persistence. xml , you need to define your own @Bean of type LocalEntityManagerFactoryBean (with an ID of 'entityManagerFactory') and set the persistence unit name there.
If your javax. persistence. * import cannot be resolved, you will need to provide the jar that implements JPA. You can do that either by manually downloading it (and adding it to your project) or by adding a declaration to a dependency management tool (for eg, Ivy/Maven/Gradle).
If we want to use JPA with MySQL database, we need the mysql-connector-java dependency. We'll also need to define the DataSource configuration. We can do this in a @Configuration class or by using standard Spring Boot properties. Spring Boot will automatically configure a data source based on these properties.
No, you cannot perform CRUD operations with JPA alone. As JPA is just a specification, you need the implementation to perform database operations. The implementations are provided by Hibernate, EclipseLink, Ibatis, etc.
There are some features of JPA that only work in XML configuration unfortunately, but I can't see anything like that in yours. I don't think persistence.xml
is loaded by default, so probably that's the issue. So why don't you go with the flow and use Java and application.properties to configure the entity manager? The JPA sample from Spring Boot has everything you need to get started. 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.
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
.
N.B. you aren't really using dependency injection very effectively in your controller - why wouldn't you just inject the UserDao
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With