After we have declared the required dependencies in our POM file, we have to configure the application context of our Spring application.

This blog post describes how we can configure the persistence layer of a Spring application that uses Spring Data JPA and Hibernate.

Let’s get started.

Additional Reading:

If you are not familiar with Spring Data JPA, you should read the following blog posts before you continue reading this blog post:

Configuring the Persistence Layer of a Spring Application

We can create the configuration class, which configures the persistence layer of a Spring application, by following these steps:

  1. Create the properties file that contains the properties used by our application context configuration class.
  2. Configure the datasource bean.
  3. Configure the entity manager factory bean.
  4. Configure the transaction manager bean.
  5. Enable annotation-driven transaction management.
  6. Configure Spring Data JPA.

But before we can get started, we have to create the configuration class that configures the persistence layer of our application. The source code of the PersistenceContext class looks as follows:

1@Configuration
2class PersistenceContext {
3
4	//Configure the required beans here
5}

Let’s start by creating the properties file.

Creating the Properties File

Often we want to use a slightly different configuration in different environments. A good way to do this is move the configuration to a properties file and use a different properties file in different environments.

The application.properties file contains the configuration that is used to configure our example application. We can create this properties file by following these steps:

  1. Configure the database connection of our application. We need to configure the name of the JDBC driver class, the JDBC url, the username of the database user, and the password of the database user.
  2. Configure Hibernate by following these steps:
  3. Configure the used database dialect.
  4. Ensure that Hibernate creates the database when our application is started and drops it when our application is closed.
  5. Configure the naming strategy that is used when Hibernate creates new database objects and schema elements.
  6. Configure the Hibernate to NOT write the invoked SQL statements to the console.
  7. Ensure that if Hibernate writes the SQL statements to the console, it will use prettyprint.

The application.properties file looks as follows:

 1#Database Configuration
 2db.driver=org.h2.Driver
 3db.url=jdbc:h2:mem:datajpa
 4db.username=sa
 5db.password=
 6
 7#Hibernate Configuration
 8hibernate.dialect=org.hibernate.dialect.H2Dialect
 9hibernate.hbm2ddl.auto=create-drop
10hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
11hibernate.show_sql=false
12hibernate.format_sql=true

The properties found from the application.properties file are loaded by the ExampleApplicationContext class. If you want to take a closer look at it, you can get it from Github.

Additional Reading:

Let’s move on and configure the datasource bean.

Configuring the Datasource Bean

We can configure the datasource bean by following these steps:

  1. Ensure that the close() method of the created DataSource object is invoked when the application context is closed.
  2. Configure the database connection. We need to set the name of the JDBC driver class, the JDBC url, the username of database user, and the password of the database user.
  3. Create a new HikariDataSource object and return the created object.

The method that configures the datasource bean looks as follows:

 1@Configuration
 2class PersistenceContext {
 3
 4	@Bean(destroyMethod = "close")
 5	DataSource dataSource(Environment env) {
 6		HikariConfig dataSourceConfig = new HikariConfig();
 7		dataSourceConfig.setDriverClassName(env.getRequiredProperty("db.driver"));
 8		dataSourceConfig.setJdbcUrl(env.getRequiredProperty("db.url"));
 9		dataSourceConfig.setUsername(env.getRequiredProperty("db.username"));
10		dataSourceConfig.setPassword(env.getRequiredProperty("db.password"));
11
12		return new HikariDataSource(dataSourceConfig);
13	}
14
15	//Add the other beans here
16}

Let’s move on and configure the entity manager factory bean.

Configuring the Entity Manager Factory Bean

We can configure the entity manager factory bean by following these steps:

  1. Create a new LocalContainerEntityManagerFactoryBean object. We need to create this object because it creates the JPA EntityManagerFactory.
  2. Configure the used datasource.
  3. Configure the Hibernate specific implementation of the JpaVendorAdapter interface. It will initialize our configuration with the default settings that are compatible with Hibernate.
  4. Configure the packages that are scanned for entity classes.
  5. Configure the JPA properties that are used to provide additional configuration to the used JPA provider.

The method that configures the entity manager factory bean looks as follows:

 1@Configuration
 2class PersistenceContext {
 3
 4	@Bean
 5	LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
 6																Environment env) {
 7		LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
 8		entityManagerFactoryBean.setDataSource(dataSource);
 9		entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
10		entityManagerFactoryBean.setPackagesToScan("net.petrikainulainen.springdata.jpa.todo");
11
12		Properties jpaProperties = new Properties();
13
14		//Configures the used database dialect. This allows Hibernate to create SQL
15		//that is optimized for the used database.
16		jpaProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
17
18		//Specifies the action that is invoked to the database when the Hibernate
19		//SessionFactory is created or closed.
20		jpaProperties.put("hibernate.hbm2ddl.auto",
21				env.getRequiredProperty("hibernate.hbm2ddl.auto")
22		);
23
24		//Configures the naming strategy that is used when Hibernate creates
25		//new database objects and schema elements
26		jpaProperties.put("hibernate.ejb.naming_strategy",
27				env.getRequiredProperty("hibernate.ejb.naming_strategy")
28		);
29
30		//If the value of this property is true, Hibernate writes all SQL
31		//statements to the console.
32		jpaProperties.put("hibernate.show_sql",
33				env.getRequiredProperty("hibernate.show_sql")
34		);
35
36		//If the value of this property is true, Hibernate will format the SQL
37		//that is written to the console.
38		jpaProperties.put("hibernate.format_sql",
39				env.getRequiredProperty("hibernate.format_sql")
40		);
41
42		entityManagerFactoryBean.setJpaProperties(jpaProperties);
43
44		return entityManagerFactoryBean;
45	}
46
47	//Add the other beans here
48}

Let’s move on and configure the transaction manager bean.

Configuring the Transaction Manager Bean

Because we are using JPA, we have to create a transaction manager bean that integrates the JPA provider with the Spring transaction mechanism. We can do this by using the JpaTransactionManager class as the transaction manager of our application.

We can configure the transaction manager bean by following these steps:

  1. Create a new JpaTransactionManager object.
  2. Configure the entity manager factory whose transactions are managed by the created JpaTransactionManager object.

The method that configures the transaction manager bean looks as follows:

 1@Configuration
 2class PersistenceContext {
 3
 4	@Bean
 5	JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
 6		JpaTransactionManager transactionManager = new JpaTransactionManager();
 7		transactionManager.setEntityManagerFactory(entityManagerFactory);
 8		return transactionManager;
 9	}
10
11	//Add the other beans here
12}

Let’s move on and enable annotation-driven transaction management.

Enabling Annotation-Driven Transaction Management

We can enable annotation-driven transaction management by annotating the PersistenceContext class with the @EnableTransactionManagement annotation. The relevant part of the PersistenceContext class looks as follows:

1@Configuration
2@EnableTransactionManagement
3class PersistenceContext {
4
5	//The beans are configured here
6}

Let’s move on and configure Spring Data JPA.

Configuring Spring Data JPA

We can configure Spring Data JPA by following these steps:

  1. Enable Spring Data JPA by annotating the PersistenceContext class with the @EnableJpaRepositories annotation.
  2. Configure the base packages that are scanned when Spring Data JPA creates implementations for our repository interfaces.

The relevant part of the PersistenceContext class looks as follows:

1@Configuration
2@EnableJpaRepositories(basePackages = {
3        "net.petrikainulainen.springdata.jpa.todo"
4})
5@EnableTransactionManagement
6class PersistenceContext {
7
8	//The beans are configured here
9}

That is all folks. We have now successfully configured the persistence layer of our example application. Let’s move on and summarize what we learned from this blog post.

Summary

This blog post has taught us two things:

  • If we need to use a different configuration in different environment, we should move this configuration to a properties file.
  • We learned to configure the persistence layer of a Spring application that uses Spring Data JPA and Hibernate.

The next part of this tutorial describes how we can create a Spring Data JPA repository that provides CRUD operations for a simple entity.

P.S. You can get the example application of this blog post from Github.

If you want to learn how to use Spring Data JPA, you should read my Spring Data JPA tutorial.