Spring Data JPA Configuration

How to use Java configuration to set up Spring Data JPA with Hibernate and Oracle.

Example Details

This example demonstrates how to:

Configure a DataSource for Oracle. Create an EntityManagerFactorBean for Hibernate. Create a TransactionManager bean. Scan the classpath for repositories.

Data Source

We configure the DataSource bean using properties from an external file.

The JDBC and connection pool properties are available from the Environment bean.

DataSourceConfig.java
package io.lishman.springdata.jpa.config;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource("classpath:/data/jdbc-dev.properties")
public class DataSourceConfig {
    
    @Autowired private Environment env;
    
    @Bean(destroyMethod="close")
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        dataSource.setMaxActive(env.getProperty("dbcp.maxActive", Integer.class));
        dataSource.setMaxIdle(env.getProperty("dbcp.maxIdle", Integer.class));
        dataSource.setMaxWait(env.getProperty("dbcp.maxWait", Integer.class));
        return dataSource;
    }
 
}

Properties

Here are the properties used to configure an Oracle DataSource and the connection pool limits.

jdbc-dev.properties
jdbc.driverClassName=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@database:1521:xe
jdbc.username=world
jdbc.password=secret

dbcp.maxActive=100
dbcp.maxIdle=30
dbcp.maxWait=20000

JPA Configuration

Now we can use the dataSource with our EntityManager factory bean.

This bean is configured with Hibernate as the JPA vendor using some additional properties from a Hibernate properties file. We use Spring-based scanning for entity classes, so there is no need for a persistence.xml file.

Finally, we configure a transaction manager. The @EnableTransactionManagement annotation can be omitted when using repositories.

JpaConfig.java
package io.lishman.springdata.jpa.config;

import java.util.Collections;

import javax.sql.DataSource;

import io.lishman.springdata.jpa.domain.DomainPackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

@Configuration
@PropertySource("classpath:/data/hibernate.properties")
public class JpaConfig {
    
    @Autowired private Environment env;
    @Autowired private DataSource dataSource;
    
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

        HibernateJpaVendorAdapter hibernateJpa = new HibernateJpaVendorAdapter();
        hibernateJpa.setDatabasePlatform(env.getProperty("hibernate.dialect"));
        hibernateJpa.setShowSql(env.getProperty("hibernate.show_sql", Boolean.class));
        
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setDataSource(dataSource);
        emf.setPackagesToScan(DomainPackage.class.getPackage().getName());
        emf.setJpaVendorAdapter(hibernateJpa);
        emf.setJpaPropertyMap(Collections.singletonMap("javax.persistence.validation.mode", "none"));
        return emf;
    }
    
    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager txnMgr = new JpaTransactionManager();
        txnMgr.setEntityManagerFactory(entityManagerFactory().getObject());
        return txnMgr;
    }

}

Hibernate Properties

Here is the Hibernate properties file used in the previous step.

hibernate.properties
hibernate.generate_statistics=false
hibernate.show_sql=false
hibernate.format_sql=false
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect

Repository Configuration

Next, we enable JPA repositories and scan the specified package for Spring Data repositories.

RepositoryConfig.java
package io.lishman.springdata.jpa.config;

import io.lishman.springdata.jpa.repository.RepositoryPackage;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@EnableJpaRepositories(basePackageClasses=RepositoryPackage.class)
public class RepositoryConfig {}

Importing configuration

For convenience, we can import these classes into a 'master' configuration class using the @Import annotation.

Config.java
package io.lishman.springdata.jpa.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({DataSourceConfig.class, JpaConfig.class, RepositoryConfig.class} )
public class Config {}