Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

This tutorial shows how to set up Spring with JPA, using Hibernate as a persistence provider.

For a step by step introduction about setting up the Spring context using Java-based configuration and the basic Maven pom for the project, see this article.

We'll start by setting up JPA in a Spring Boot project, then we'll look into the full configuration we need if we have a standard Spring project.

Further reading:

Defining JPA Entities

Learn how to define entities and customize them using the Java Persistence API.

Spring Boot with Hibernate

A quick, practical intro to integrating Spring Boot and Hibernate/JPA.

Here is a video on setting up Hibernate 4 with Spring 4 (I recommend watching it in full 1080p):

2. JPA in Spring Boot

The Spring Boot project is intended to make creating Spring applications much faster and easier. This is done with the use of starters and auto-configuration for various Spring functionalities, JPA among them.

2.1. Maven Dependencies

To enable JPA in a Spring Boot application, we need the spring-boot-starter and spring-boot-starter-data-jpa dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

The spring-boot-starter contains the necessary auto-configuration for Spring JPA. Also, the spring-boot-starter-jpa project references all the necessary dependencies such as hibernate-entitymanager.

2.2. Configuration

Spring Boot configures Hibernate as the default JPA provider, so it's no longer necessary to define the entityManagerFactory bean unless we want to customize it.

Spring Boot can also auto-configure the dataSource bean, depending on the database we're using. In the case of an in-memory database of type H2, HSQLDB, and Apache Derby, Boot automatically configures the DataSource if the corresponding database dependency is present on the classpath.

For example, if we want to use an in-memory H2 database in a Spring Boot JPA application, we only need to add the h2 dependency to the pom.xml file:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.200</version>
</dependency>

This way, we don't need to define the dataSource bean, but we can do so if we want to customize it.

If we want to use JPA with MySQL database, then we need the mysql-connector-java dependency, as well as to define the DataSource configuration.

We can do this in a @Configuration class, or by using standard Spring Boot properties.

The Java configuration looks the same as it does in a standard Spring project:

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUsername("mysqluser");
    dataSource.setPassword("mysqlpass");
    dataSource.setUrl(
      "jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true"); 
    
    return dataSource;
}

To configure the data source using a properties file, we have to set properties prefixed with spring.datasource:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=mysqluser
spring.datasource.password=mysqlpass
spring.datasource.url=
  jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true

Spring Boot will automatically configure a data source based on these properties.

Also in Spring Boot 1, the default connection pool was Tomcat, but with Spring Boot 2 it has been changed to HikariCP.

You can find more examples of configuring JPA in Spring Boot in the GitHub project.

As we can see, the basic JPA configuration is fairly simple if we're using Spring Boot.

However, if we have a standard Spring project, then we need more explicit configuration, using either Java or XML. That's what we'll focus on in the next sections.

3. The JPA Spring Configuration With Java – in a Non-Boot Project

To use JPA in a Spring project, we need to set up the EntityManager.

This is the main part of the configuration and we can do it via a Spring factory bean. This can be either the simpler LocalEntityManagerFactoryBean or the more flexible LocalContainerEntityManagerFactoryBean.

Let's see how we can use the latter option:

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{

   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean em 
        = new LocalContainerEntityManagerFactoryBean();
      em.setDataSource(dataSource());
      em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });

      JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
      em.setJpaVendorAdapter(vendorAdapter);
      em.setJpaProperties(additionalProperties());

      return em;
   }
   
   // ...

}

We also need to explicitly define the DataSource bean we've used above:

@Bean
public DataSource dataSource(){
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa");
    dataSource.setUsername( "tutorialuser" );
    dataSource.setPassword( "tutorialmy5ql" );
    return dataSource;
}

The final part of the configuration are the additional Hibernate properties and the TransactionManager and exceptionTranslation beans:

@Bean
public PlatformTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());

    return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
    return new PersistenceExceptionTranslationPostProcessor();
}

Properties additionalProperties() {
    Properties properties = new Properties();
    properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
       
    return properties;
}

4. The JPA Spring Configuration With XML

Next, let's see the same Spring Configuration with XML:

<bean id="myEmf" 
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.baeldung.persistence.model" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        </props>
    </property>
</bean>

<bean id="dataSource" 
  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/spring_jpa" />
    <property name="username" value="tutorialuser" />
    <property name="password" value="tutorialmy5ql" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven />

<bean id="persistenceExceptionTranslationPostProcessor" class=
  "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

There's a relatively small difference between the XML and the new Java-based configuration. Namely, in XML, a reference to another bean can point to either the bean or a bean factory for that bean.

In Java, however, since the types are different, the compiler doesn't allow it, and so the EntityManagerFactory is first retrieved from its bean factory and then passed to the transaction manager:

transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());

5. Going Full XML-less

Usually, JPA defines a persistence unit through the META-INF/persistence.xml file. Starting with Spring 3.1, the persistence.xml is no longer necessary. The LocalContainerEntityManagerFactoryBean now supports a packagesToScan property where the packages to scan for @Entity classes can be specified.

This file was the last piece of XML we need to remove. We can now set up JPA fully with no XML.

We would usually specify JPA properties in the persistence.xml file. Alternatively, we can add the properties directly to the entity manager factory bean:

factoryBean.setJpaProperties(this.additionalProperties());

As a side note, if Hibernate would be the persistence provider, then this would be the way to specify Hibernate specific properties as well.

6. The Maven Configuration

In addition to the Spring Core and persistence dependencies – show in detail in the Spring with Maven tutorial – we also need to define JPA and Hibernate in the project, as well as a MySQL connector:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>5.4.13.Final</version>
   <scope>runtime</scope>
</dependency>

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>8.0.19</version>
   <scope>runtime</scope>
</dependency>

Note that the MySQL dependency is included here as an example. We need a driver to configure the datasource, but any Hibernate-supported database will do.

7. Conclusion

This tutorial illustrated how to configure JPA with Hibernate in Spring in both a Spring Boot and a standard Spring application.

As always, the code presented in this article is available over on GitHub.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
43 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
eugene
eugene
7 years ago

Hi.. can’t seem to make it work. I deleted my persistence.xml and have my config in JPA context file.
When I have persistence.xml, with empty persistence unit. i get an error that class is not mapped. when i deleted persistence.xml i have this error: no persistence.xml.

Do you know how to solve this?

Eugen Paraschiv
7 years ago
Reply to  eugene

Did you try to clone the example project? That should give a good base to build your JPA configuration upon. If you find any problem starting from this point – please go ahead and create an issue on github and I’ll look into it.
Thanks. Eugen.

eugene
eugene
7 years ago

I tried importing your spring-jpa project. and found no major differences on the setup/configuration. What I noticed is that, the JPA Facets is not clicked in your project. Apparently, this solves my issue when I removed it. Thanks a lot.

ps
regarding the config above, may i know what’s advisable? using the java config or the xml – jpaConfig? I’m also wondering where are your dispatcher servlet and view resolvers configured. (sorry, just started learning spring/jpa-hibernate) TIA.

Eugen Paraschiv
7 years ago
Reply to  eugene

Glad the sample project helped. As for what to use – java or XML config, these are very much equivalent, so it’s a matter of preference. I a new project, I personally prefer to use java config. The Dispatcher, controllers and generally the web configuration lives in a different config file – this one is simply persistence, with the goal to keep things as separate and decoupled as possible.

Abhi
Abhi
4 years ago

Hey Eugen

i wanted to connect two database in the project with this method
how do you think it is possible using this method

Lukas Eder
6 years ago

I don’t think it’s a good idea to create an anonymous inner class that extends Properties. As any inner class, this will keep a reference to its outer class – PersistenceJPAConfig, in this case. This instance (and the outer class reference) are then passed to the LocalContainerEntityManagerFactoryBean (what a class name 😉 ) whose lifecycle might be quite different now or in the future, just to save 1-2 lines of code.

Creating such anonymous classes is almost always a bad idea, see Rule #3 of our article here.

Eugen Paraschiv
6 years ago
Reply to  Lukas Eder

Hey Lukas,
Thanks for the suggestion – you’re absolutely right – no point in holding on to that reference. I updated the tutorial code and the article to simply initialize a Properties object.
Cheers,
Eugen.

Abhi
Abhi
4 years ago
Reply to  Lukas Eder

Hey Lukas,

Can you please tell me a way how to configure two databases with this method.

Lukas Eder
4 years ago
Reply to  Abhi

Hey Abhi, sorry, I’m not quite sure what you mean…? Perhaps you meant to direct your question to Eugen, instead?

Amara Bargougui
Amara Bargougui
5 years ago

Hi,
thank you for this tutorial
where could we define the persistance_unit when we remove persistance.xml file?

Amara Bargougui
Amara Bargougui
5 years ago

I think i found the answer :

this should be the solution:

cf : JAVADOC :
getPersistenceUnitName() :

Return the name of the persistence unit used to create this EntityManagerFactory, or null if it is an unnamed default.

noviceUser
noviceUser
5 years ago

Hi

How to define a persistent unit name if we dont want to use default.

Thanks in advance

Amara Bargougui
Amara Bargougui
5 years ago
Reply to  noviceUser

Hi,

like i said, in this case, you have just to valorize the ‘persistenceUnitName’ property

cf answer above

Mihai Scripca
Mihai Scripca
5 years ago

How about when you need to add queries to persistence.xml? Seems that are some problems when calling: namedQueries/trade-booking-log.jpa.xml in persistence.xml…

Eugen Paraschiv
5 years ago
Reply to  Mihai Scripca

Hey Mihai – the simple solution presented here doesn’t use a persistence.xml – it’s no longer necessary. I would recommend simply defining your queries at the repository/DAO level directly. You can still define named queries via annotations of course, if you need them, and still not worry about the persistence.xml. Hope that helps. Cheers,
Eugen.

noviceUser
noviceUser
5 years ago

Hi.. very helpful tutorial.. I took help of your tutorial and I have one request regarding using entitymanager. Could you please help me on that? I need to pass entitymanager like below :

JPAQuery jpaQuery = new JPAQuery(entityManager);

How can I set entitymanager to JPAQuery

Thanks in advance.

Eugen Paraschiv
5 years ago
Reply to  noviceUser

Hey,
First, I assume you have control over the JPAQuery – you’re instantiating that manually. You simply need to wire in your EntityManager and then pass it to your query object. Hope it helps. Cheers,
Eugen.

Comments are closed on this article!