Do want to get a better understanding of Spring web application architecture? If so, get started right now!

Spring Data JPA Tutorial Part One: Configuration

The begin of a chess game

Spring Data JPA is a project which aims both to simplify the creation of JPA based repositories and to reduce the amount of code needed to communicate with a database. I have been using it for a while at my work and in my personal hobby projects and it has indeed make things a lot more simpler and cleaner. Now it is time to share my knowledge with you.

This is the first part of my Spring Data JPA tutorial and it will describe to you, how you can configure Spring Data JPA when you are using Hibernate as your JPA provider. Before we will get started, I want to make one thing straight: This tutorial is not an introductory level tutorial to Hibernate, JPA or Spring. You must have some experience about these technologies if you want to understand the concepts described in my Spring Data JPA tutorial.

The dependencies of this tutorial are following:

  • BoneCP 0.7.1.RELEASE (You can use other data source implementations as well)
  • Hibernate 4.0.1.Final
  • Spring Framework 3.1.0.RELEASE
  • Spring Data JPA 1.0.2
  • Servlet API 3.0

Also, since I am using Maven as a build tool, you must install it if you want to run my example application.

Getting Started

It is time to get started. You can configure the Spring Data JPA by following these steps:

  • You have to obtain the needed dependencies.
  • You must configure the needed beans in your Spring application context configuration. The beans needed by the Spring Data JPA are: data source, transaction manager and entity manager factory.
  • You have to configure the Spring Data JPA.

These steps are explained with more details in following:

Obtaining the Needed Depedencies

First, you need to obtain the needed dependencies. You can do this by configuring the needed dependencies in your pom.xml file. The pom.xml of my example looks following:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.petrikainulainen.spring</groupId>
    <artifactId>data-jpa-tutorial-part-one</artifactId>
    <packaging>war</packaging>
    <version>0.1</version>
    <name>Spring Data JPA Tutorial Part One</name>
    <description>Spring Data JPA Tutorial Part One</description>
    <licenses>
        <license>
            <name>Apache License 2.0</name>
            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
        </license>
    </licenses>
    <url>http://www.petrikainulainen.net</url>
    <repositories>
        <repository>
            <id>repository.jboss.org-public</id>
            <name>JBoss repository</name>
            <url>https://repository.jboss.org/nexus/content/groups/public</url>
        </repository>
    </repositories>
    <properties>
        <hibernate.version>4.0.1.Final</hibernate.version>
        <mysql.connector.version>5.1.18</mysql.connector.version>
        <slf4j.version>1.6.1</slf4j.version>
        <spring.version>3.1.0.RELEASE</spring.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- Spring Framework -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- Spring MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
        <!-- Spring Data JPA -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.0.2.RELEASE</version>
        </dependency>
        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <!-- H2 Database -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.3.160</version>
        </dependency>
        <!-- MySQL JDBC connector -->
        <!-- If you want to use MySQL, uncomment this dependency declation. -->
        <!--
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.connector.version}</version>
        </dependency>
        -->
        <!-- PostgreSQL JDBC 4 -->
        <!-- If you don't want to use PostgreSQL, uncomment this dependency declaration. -->
        <!--
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.0-801.jdbc4</version>
        </dependency>
        -->
        <!-- BoneCP -->
        <dependency>
            <groupId>com.jolbox</groupId>
            <artifactId>bonecp</artifactId>
            <version>0.7.1.RELEASE</version>
        </dependency>
        <!-- Servlet API 3.0 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- Logging dependencies -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
        <!-- Testing Dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>data-jpa-tutorial-part-one</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>8.1.0.RC2</version>
                <configuration>
                    <scanIntervalSeconds>0</scanIntervalSeconds>
                    <webAppConfig>
                        <defaultsDescriptor>src/main/resources/webdefault.xml</defaultsDescriptor>
                    </webAppConfig>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-site-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <reportPlugins>
                        <!-- Cobertura Plugin -->
                        <plugin>
                            <groupId>org.codehaus.mojo</groupId>
                            <artifactId>cobertura-maven-plugin</artifactId>
                            <version>2.5.1</version>
                        </plugin>
                    </reportPlugins>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Configuring the Spring Application Context

Second, you must configure the Spring application context. As you might remember, you need to configure the data source, transaction manager and entity manager factory beans. If you are using Spring 3.1 and Servlet 3.0, you can do this by implementing a Java configuration class and loading that configuration class in your web application initializer. The content of my application context configuration class is given in following:

import com.jolbox.bonecp.BoneCPDataSource;
import org.hibernate.ejb.HibernatePersistence;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.*;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * An application context Java configuration class. The usage of Java configuration
 * requires Spring Framework 3.0 or higher with following exceptions:
 * <ul>
 *     <li>@EnableWebMvc annotation requires Spring Framework 3.1</li>
 * </ul>
 * @author Petri Kainulainen
 */
@Configuration
@ComponentScan(basePackages = {"net.petrikainulainen.spring.datajpa.controller"})
@EnableWebMvc
@ImportResource("classpath:applicationContext.xml")
@PropertySource("classpath:application.properties")
public class ApplicationContext {
    
    private static final String VIEW_RESOLVER_PREFIX = "/WEB-INF/jsp/";
    private static final String VIEW_RESOLVER_SUFFIX = ".jsp";

    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
    private static final String PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY = "hibernate.ejb.naming_strategy";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";

    private static final String PROPERTY_NAME_MESSAGESOURCE_BASENAME = "message.source.basename";
    private static final String PROPERTY_NAME_MESSAGESOURCE_USE_CODE_AS_DEFAULT_MESSAGE = "message.source.use.code.as.default.message";

    @Resource
    private Environment environment;

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

        dataSource.setDriverClass(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
        dataSource.setJdbcUrl(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
        dataSource.setUsername(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
        dataSource.setPassword(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));

        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager() throws ClassNotFoundException {
        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());

        return transactionManager;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws ClassNotFoundException {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPackagesToScan(environment.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
        entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);

        Properties jpaProterties = new Properties();
        jpaProterties.put(PROPERTY_NAME_HIBERNATE_DIALECT, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
        jpaProterties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
        jpaProterties.put(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY));
        jpaProterties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));

        entityManagerFactoryBean.setJpaProperties(jpaProterties);

        return entityManagerFactoryBean;
    }

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

        messageSource.setBasename(environment.getRequiredProperty(PROPERTY_NAME_MESSAGESOURCE_BASENAME));
        messageSource.setUseCodeAsDefaultMessage(Boolean.parseBoolean(environment.getRequiredProperty(PROPERTY_NAME_MESSAGESOURCE_USE_CODE_AS_DEFAULT_MESSAGE)));

        return messageSource;
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix(VIEW_RESOLVER_PREFIX);
        viewResolver.setSuffix(VIEW_RESOLVER_SUFFIX);

        return viewResolver;
    }
}

My web application initializer looks like this:

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.*;

/**
 * Web application Java configuration class. The usage of web application
 * initializer requires Spring Framework 3.1 and Servlet 3.0.
 * @author Petri Kainulainen
 */
public class DataJPAExampleInitializer implements WebApplicationInitializer {
    
    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
    private static final String DISPATCHER_SERVLET_MAPPING = "/";
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ApplicationContext.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(rootContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING);

        servletContext.addListener(new ContextLoaderListener(rootContext));
    }
}

You might have noticed that I used the @PropertySource annotation to specify the location of a properties file which contains the values of used configuration parameters. The content of my application.properties file is following:

# The default database is H2 memory database but I have also
# added configuration needed to use either MySQL and PostgreSQL.

#Database Configuration
db.driver=org.h2.Driver
#db.driver=com.mysql.jdbc.Driver
#db.driver=org.postgresql.Driver
db.url=jdbc:h2:mem:datajpa
#db.url=jdbc:mysql://localhost:3306/datajpa
#db.url=jdbc:postgresql://localhost/datajpa
db.username=sa
db.password=

#Hibernate Configuration
hibernate.dialect=org.hibernate.dialect.H2Dialect
#hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
#hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.format_sql=true
hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
hibernate.show_sql=true

#MessageSource
message.source.basename=i18n/messages
message.source.use.code.as.default.message=true

#EntityManager
#Declares the base package of the entity classes
entitymanager.packages.to.scan=net.petrikainulainen.spring.datajpa.model

Configuring Spring Data JPA

Third, you must configure the Spring Data JPA. If you were paying attention, you might have noticed that I used the @ImportResource annotation in my application context configuration class to import additional configuration from a XML configuration file. At the moment Spring Data JPA does not support Java configuration. Thus, the only way to configure it is to use a XML configuration file. My applicationContext.xml file looks following:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
    <!--
        Configures the location of static resources such as css files.
        Requires Spring Framework 3.0 or higher.
    -->
    <mvc:resources mapping="/static/**" location="/static/"/>

    <!--
        Ensures that dispatcher servlet can be mapped to '/' and static resources
        are still served by the containers default servlet. Requires Spring Framework
        3.0 or higher.
    -->
    <mvc:default-servlet-handler/>

    <!--
        Configures Spring Data JPA and sets the base package of my DAOs.
    -->
    <jpa:repositories base-package="net.petrikainulainen.spring.datajpa.repository"/>
</beans>

You Are Done

That is it. I have now demonstrated to you how you can configure the Spring Data JPA. I also have created an example application to demonstrate that this configuration is actually working. You can test the configuration yourself by getting my example application from Github and running the example web application by using the Maven Jetty plugin (Note: Remember to create the model and repository packages first. Since it is not possible to add empty directories to the Git staging area, the Github repository does not have them either).

The second part of my Spring Data JPA tutorial describes how you can create a simple CRUD web application by using Spring Data JPA. Stay tuned.

If you want to learn more about Spring Data JPA, you should read all parts of my Spring Data JPA tutorial.

About the Author

Petri Kainulainen is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.

About Petri Kainulainen →

73 comments… add one

  • excellent article very helpfull!!

    can you also explain how to set up a simple hibernate4 and spring3.1 web application without using jpa. especially the part about how to use LocalSessionFactoryBuilder.

    Thanks.

    Reply
  • Hi Petri,
    I need help in testing declarative transaction handling by spring; Pls dont mind if it is nor related to current thread discussion. I am using Junit to test this, not getting this worked. Here is my simple Junit. Here, the attribute I given, defaultRollback = false means I want to see the row inserted in the table, and if defaultRollback = true,
    it is not inserting the record and finally logs message ”Rolled back transaction after test execution for the context……showing exception..java.lang.NullPointerException.”. Even no exception arised, the transaction is getting rolled back and never inserting the record in the table.

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "file:WebContent/WEB-INF/applicationContext.xml")
    @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
    public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Test
    @Transactional
    public void testAddUser() {
    User user = new User();

    user.setFirstName("Dhana");
    user.setLastName("Kumar");
    user.setUserName("anemdhana");
    user.setEmail("dhana.anem@gmail.com");
    user.setAge(27);
    user.setJoinedOn(new Date(System.currentTimeMillis()));
    user.setActive(true);

    userService.addUser(user);

    Role role = roleService.findRole(99L);

    // here NPE will be thrown and hence entire transaction must be rolled back.
    System.out.println(role.getName());
    }
    }

    Reply
  • Hi Petri,

    Am trying your Spring Data JPA examples. Standard install and run with Jetty no problem.
    However when trying to import the projects in Eclipse i am getting reference errors on spring-jpa-1.0
    schema referenced from applicationContext. Following a tip on a forum I updated version to 1.2.0.RELEASE instead of 1.0.2.RELEASE.
    But still not able to build from Eclipse.
    Can you give me a tip here.

    Thx
    Dirk

    Reply
    • The Spring Data JPA 1.0.2 had a “bug” that caused schema validation errors when STS was used. See this bug report for more details: DATAJPA-160.

      However, as the bug report indicates, this should not cause build failure. When you updated the Spring Data JPA to version1.2.0.RELEASE, did you update both the dependency version (found from pom.xml file) and the application context configuration file?

      Also, since you are using Spring Data JPA version 1.2.0, you do not have to configure Spring Data JPA by using XML. You can start using Java configuration by following these steps:

      1. Update the pom.xml file and set the dependency version of Spring Data JPA to 1.2.0.RELEASE.
      2. Remove the repositories element and the schema declaration from the applicationContext.xml file.
      3. Annotate the ApplicationContext class with the @EnableJpaRepositories annotation and set the base package of your repositories as its value. See the Javadoc of the @EnableJpaRepositories annotation for more details.

      This should solve your problem.

      Reply
      • Petri,

        I downloaded your source code and loaded the project in STS. When I deployed it to the built-in vFabric tc server it worked fine. I made the changes you listed above and tried deploying it again, but I got a 404 for the home view. Backing out the steps, the 404 seemed related to the modifications to applicationContext.xml. In the end I kept the updated dependency version in the POM and updated the version number in the schema statement to get rid of the error in STS.

        Thanks for this tutorial series!

        Reply
        • Hi Josh,

          I am glad to hear that you liked my tutorial. About your problem, did you end up using the XML configuration since the Java configuration did not work in the built-in vFabric tc server?

          Reply
  • I am using a combination of Java configuration and XML configuration, but I had to use the jpa:repositories element in the XML configuration. The 404 in my case seemed to be related to using the @EnableJpaRepositories annotation instead of the xml element.

    Reply
  • Thanks a lot for all the articles…
    Its people like you that make internet fun and useful!! cheers !!!

    Reply
    • You are welcome. By the way, your comment just made my day!

      Reply
  • Why do I need extra information , I like to read example working of Spring Data.
    What is deal with servlet ? Spring config file and main are good enough. Sorry there are too much irrelevant information on the web.

    Reply
    • The web application initializer is used to configure the web application by using Java configuration. It has the following responsibilities:

      1. Create a new ‘root’ application context.
      2. Register the application application context configuration class to the ‘root’ application context.
      3. Register and map the dispatcher servlet.
      4. Use a context loader listener to manage the lifecycle of the ‘root’ application context.

      In other words, your web application would not do much without the web application initializer (unless you use web.xml for configuring your web application). You can get more information about the WebApplicationInitializer from the API documentation of Spring Framework.

      I hope that this answered to your question.

      Reply
  • Too complicate . Just explain how to configure DB connection and interface .
    and show simple main class to test it. In you explanation I got lost in the first step.

    Reply
  • Petri ,
    Could you explain about configuration. We need a file (I don’t like annotation )
    for DB connection. Is’ it ? What is a file name ? location ? and content?
    What is a file contains repository definition is it a standard Spring name and where is a correct location for it ??.

    Reply
    • Of course. You can create the Spring application context configuration file by following these steps:

      1. Create a properties file that contains the properties used in your application context configuration file. This step is not mandatory but it makes your configuration a bit cleaner.
      2. Read the property values from the properties file. If you don’t want to use properties file, you can skip this step.
      3. Configure the data source bean.
      4. Configure the entity manager factory bean.
      5. Configure the transaction manager bean.
      6. Enable @Transactional annotations.
      7. Configure Spring Spring Data JPA.

      The name of the created properties file is application.properties and its content looks as follows:

      #Database Configuration
      db.driver=org.h2.Driver
      db.url=jdbc:h2:mem:datajpa
      db.username=sa
      db.password=
      
      #Hibernate Configuration
      hibernate.dialect=org.hibernate.dialect.H2Dialect
      hibernate.format_sql=true
      hibernate.hbm2ddl.auto=create-drop
      hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
      hibernate.show_sql=true
      


      The application context configuration (applicationContext-persistence.xml) file looks as follows:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/data/jpa 
          http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
          http://www.springframework.org/schema/tx 
          http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
          http://www.springframework.org/schema/context 
          http://www.springframework.org/schema/context/spring-context-3.1.xsd">
      
        <!-- Read the property values from application.properties -->
        <context:property-placeholder location="classpath:application.properties"/>
      
        <!-- Configure the data source bean -->
        <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
          <property name="driverClass" value="${db.driver}"/>
          <property name="jdbcUrl" value="${db.url}"/>
          <property name="username" value="${db.username}"/>
          <property name="password" value="${db.password}"/>
        </bean>
      
        <!-- Create default configuration for Hibernate -->
        <bean id="hibernateJpaVendorAdapter" 
          class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
      
        <!-- Configure the entity manager factory bean -->
        <bean id="entityManagerFactory" 
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
          <property name="dataSource" ref="dataSource"/>
          <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
          <!-- Set the base package of your model classes -->
          <property name="packagesToScan" value="foo.bar.model"/>
          <property name="jpaProperties">
            <props>
              <prop key="hibernate.dialect">${hibernate.dialect}</prop>
              <prop key="hibernate.ejb.naming_strategy">${hibernate.naming_strategy}</prop>
              <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
              <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
              <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            </props>
          </property>
        </bean>
      
        <!-- Configure the transaction manager bean -->
        <bean id="transactionManager" 
          class="org.springframework.orm.jpa.JpaTransactionManager">
          <property name="entityManagerFactory" ref="entityManagerFactory"/>
        </bean>
      
        <!-- Enable @Transactional annotations -->
        <tx:annotation-driven/>
      
        <!-- 
          Configure Spring Data JPA and set the base package of the 
          repository interfaces 
        -->
        <jpa:repositories base-package="foo.bar.repository"/>
      </beans>
      


      Both of these files must be found from the classpath. If you are using Maven, you should put these files to the ‘src/main/resources directory’.

      I hope that this answered to your question.

      Reply
      • Thank you so much for All you tutorials and with this answer too.

        Reply
        • You are welcome. I am happy to hear that these tutorials have been useful to you.

          Reply
  • Wow only now realized your Tutorials http://www.petrikainulainen.net/tutorials/

    excellent reference, very nice .

    great job , very helpful.

    Thanks again!

    Reply
    • Thank you for your kind words.

      I created that page because I wanted to provide a shortcut to the good stuff which I have written. I am happy hear that you like it.

      Reply
  • Hi Petri, I hope I am not going to waste your time since I am a newbie here, first thank you about all the efforts you are doing so others can learn.

    please what did you mean by this (and how to do it ?) :

    (Note: Remember to create the model and repository packages first. Since it is not possible to add empty directories to the Git staging area, the Github repository does not have them either).
    thanks lot

    Reply
    • Don’t worry about wasting my time. It is always nice to help other people.

      About your question:

      It is not possible to add empty directory to a Git repository. This means that if you get the example application of this blog post from Github, you have to create the following packages:

      • The net.petrikainulainen.spring.datajpa.model is the base package of model classes.
      • The net.petrikainulainen.spring.datajpa.repository is the base package of Spring Data JPA repositories.

      These packages are not found from Github because they don’t have any classes yet. That is why you have to create them yourself.

      I hope that this answered to your question.

      Reply
  • Hi petri, I am trying to run de example in eclipse IDE but when deploy in jboss
    I get this ERROR Message:
    ERROR …[org.springframework.web.servlet.tags.MessageTag] (http-localhost-127.0.0.1-8080-1) No WebApplicationContext found: no ContextLoaderListener registered?: java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
    No Spring WebApplicationInitializer types detected on classpath

    Can you give me some advice about the problem.

    thanks in advance

    Reply
    • I started to wonder if it possible to run this application with JBoss because it uses Java configuration for configuring the application context and the web application.

      I did some research and found out that there is an open issue about this in the JBoss issue tracker. I am not a JBoss expert but the issue is not resolved so I assume that Java configuration is not supported at the moment.

      If this is true, you have to

      1. Create an application context configuration file.
      2. Create a web.xml file. Check out this blog post for more details about this (Search for a heading ‘Spring Configuration’).
      3. Delete the Java configuration classes (ApplicationContext and DataJPAExampleInitializer).

      I hope that this answered to your question.

      Reply
      • Thank… I choose a tomcat 7 server and I already running this tutorial.

        Reply
        • Great!

          I think that Tomcat is often the best choice for running Spring web applications in the production environment.

          I like to use the Maven Jetty plugin in development environment but Tomcat works just fine like you said.

          Reply
  • Hi ,
    I create interface
    public interface GreetingRepo extends Repository {

    S save(S entity);
    T findOne(ID primaryKey);
    Iterable findAll();
    }

    and and into applicationContext.xml

    but where I use it define @Autowired
    GreetingRepo repo;

    repo.findAll(); I got java.lang.NullPointerException.
    What is miss here?
    Any idea ?

    Reply
    • Hi Boris,

      When you create repository interfaces, you must provide two type parameters: type of the entity and type of the entity’s id.

      I assume that the name of your entity class is Greeting and the type of its id is Long.

      Also, I create the repository interface by extending the CrudRepository interface instead of the Repository interface. This way I don’t have declare the repository methods manually.

      In other words, your repository interface should look like this:

      
      public interface GreetingRepo extends CrudRepository<Greeting, Long> {
      	
      }
      
      

      I noticed that your original repository interface extends the Repository interface (instead of JpaRepository or CrudRepository). If you want to specify your repository methods manually, you have to create an intermediate interface and copy the method declarations to that interface. If you want to use the save(), findOne(), and findAll() methods, your repository interfaces should look like this:

      
      //Intermediate interface
      interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
        	T findOne(ID id);
        	Iterable<T> findAll();
      	T save(T entity);
      }
      
      //Repository interface
      public interface GreetingRepo extends MyBaseRepository<Greeting, Long> {
      
      }
      
      

      More information:

      I hope that this answered to your question.

      Reply
  • Hi Petri,

    I have created un jar with several JPA repository in it and it works fine when I tested it in the same project. But now I need to use those JPA Repositories (they are interfaces extends JpaRepository) in another project, so I imported the jar into my new project, then I got the err like: “No unique bean of type [**.****.**.ClientRepository] is defined: expected single bean but found 0″. Apparently it failed to load those JPA Repositories beans. I felt quite confused and I’m new for JPA so please help me out.

    Note: I used @EnableJpaRepositories(basePackages=”**.***.***.repository”) in the ApplicationContexte.java, and I noticed that annotation seems doesn’t work by giving un package from an external jar. Is that the reason?

    Thank you very much and your articles are really great.

    Sawakito

    Reply
  • Out of curiosity, i just tried it out.
    Indeed, with JavaConfig and @EnableJpaRepositories it does not work. With XML there is no problem.
    A Demo Project could be found here: https://github.com/dilgerma/spring-data-tutorial.

    Tested with spring-data 1.3.2

    Reply
    • Thanks a lot Martin!

      Reply
  • Hello Petri!

    Thank you for your tutorial!
    I am having one question: how i can run this sample project on Tomcat?
    Need to create web.xml?
    When i run project on Tomcat, i saw something like that: http://gyazo.com/6e051e955da54de0b2878815d712150f
    But under Jetty it is working very well.
    (It not mere curiosity, I want to use your configuration pattern on production :-)

    Reply
    • Hi,

      I noticed that you use Tomcat 6. If you want to configure your web application by using Java configuration, you have to use a servlet container which supports the servlet 3.0 specification. In other words, you have to use Tomcat 7 (I just tested this with Tomcat 7.0.40 and it was working).

      If you have to use Tomcat 6, you have to replace the class which implements the WebApplicationInitializer interface with a web.xml file.

      Remember that you can still configure the application context by using Java configuration (no need to replace those classes with XML configuration files)!

      Reply
  • Thank you Petri!
    I will be using Tomcat 7
    And I best fan of configuring application from Java.

    Reply
  • Petri – you really rock! Thanks for such a great article.

    Reply
    • You are welcome. I am happy to hear that this tutorial was useful to you!

      Reply
  • Great reference! Thank you very much for sharing.
    Cheers..

    Reply
    • You are welcome!

      Reply
  • Excellent material.
    Not only did you put time and effort in sharing this, but you also patiently answer(all sorts of) questions.
    Respect.

    Reply
    • Thank you for your kind words! You just made my day.

      Reply
  • Hi Petri,
    congratulations for your blog, it has helped me a lot in the first steps with Spring JPA.

    Now I’m facing some troubles trying to set up a project with two different databases. What I try to do is manage data from two different MySQL databases. I’ve tried to duplicate the code in ApplicationContext.java creating two different DataSource, LocalContainerEntityManagerFactoryBean and JpaTransactionManager. I have also added the corresponding parameters in application.properties file. But when I run the code, at the point in which creates the XXXRepository (the first bean), it generates an exception **No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2**.

    I think that I have to inject the concrete PersistenceContext in some way but I do not know exactly where to do that, in the Repository, in the Service…

    Could you please tell me what I’m doing wrong?

    Thanks a lot for your time and your interest.

    Reply
    • Hi José,

      I am happy to hear that my blog has been useful to you!

      About your problem:

      When I read your comment, I got the impression that you have the following requirements:

      • You have two groups of entities: A and B. The entities belonging to a group A are “stored” to the database A and the entities belonging to the group B are “stored” to the database B.
      • You want to create different entity managers and transaction managers for databases A and B.

      If this is the case, you should read this blog post which describes how you can use Spring Data JPA with multiple databases.

      I hope that this answer will help you to solve your problem.

      Reply
  • Very clean coding… Nice work Petri +1

    Reply
    • Thanks! I really appreciate your kind words.

      Reply
  • Hi Petri,

    Could you please explain me why you would still keep the applicationContext.xml?

    I created the following class:

    
    @EnableWebMvc
    @Configuration
    @ComponentScan(basePackages = "org.foo.bar.controller")
    public class WebMvcConfig extends WebMvcConfigurerAdapter{
         @Override
         public void addResourceHandlers(final ResourceHandlerRegistry registry){
              registry.addResourceHandler("/static/**").addResourceLocations("/static/");
         }
    }
    
    

    Modified the WebApplicationInitializer to the following:

    
    webApplicationContext.register(ApplicationConfig.class, WebMvcConfig.class);
    
    

    and added the following annotation to the ApplicationConfig class: @EnableJpaRepositories(basePackages = "org.foo.bar.repository")

    this seems to do the work and allows me to get rid of the xml files. Am I missing something?

    Otherwise I really appreciate your tutorials. By far the best on the subject. I’d love on advanced predication with querydsl. like linked tables e.g. select * from table_1 where a in (select a from table_2 where whatever). This is one thing that eludes me a bit :) (I’m a complete Business Project Manager)

    Reply
    • Hi Francois,

      There is no reason to use the XML configuration anymore. This tutorial is based on Spring Data 1.0.X and this version didn’t support Java configuration yet. In other words, your configuration looks good to me (I prefer Java configuration over XML configuration).

      I added your suggestion to my todo list. This is a quite common question so I guess that I should write about it in the near future (I could cover the JPA Criteria API as well).

      Reply
      • Hi Petri,

        Excellent tutorials. Whilst trying to remove the xml app config however like this post I keep getting the following:
        java.lang.IllegalStateException: LifecycleProcessor not initialized – call ‘refresh’ before invoking lifecycle methods via the context: WebApplicationContext for namespace ‘dispatcher-servlet': startup date [Tue Feb 11 01:02:05 GMT 2014]; root of context hierarchy

        I’ve followed Francois’ steps and tried with spring data jpa versions 1.2 and 1.4.3.

        It would be great to see this one updated with latest versions were appropriate and the java based config.

        Cheers,
        D

        Reply
  • Hi,

    I have never seen that exception before but you could take a look at the example application of my Spring Social tutorial. It configures Spring Data JPA by using Java configuration (no XML). You can get the configuration class from Github.

    I agree that it would be nice if I could update this tutorial to use the latest version of Spring Data JPA. I will try to find the time to do this.

    Reply
    • Thanks Petri – I’ll try the other tutorial and hopefully get my config working.

      Reply
  • I am trying to configure Spring Data with spring MVC application and run on Tomcat server. I tried both XML and Java configuration ways. But it doesn’t run when I add dependent jars. Could you please help me with this. I have a created a normal web application and controller and services.
    Thanks in Advance

    Reply
    • I have a few questions to you:

      • Which Tomcat version do you use?
      • Do you configure your web application by using Java configuration or do you use web.xml?
      • What exactly happens when you try to run the application?

      If you answer to these questions, I might be able to figure out what your problem is.

      Reply
  • Petri, I have two data sources with different credentials and database and host server names. The datasource_one has regular tables and views where as datasource_two has stored procedures for authentication and authorization. How do I map both datasources and get them CDI’s inside the application. Do you have any simple tutorial or example that we can follow. Appreciate any help.
    Tks.

    Reply
  • Hi Petri, I tried to apply the basic principles of your post in my web application, but I still can’t make the service I developed work. The service uses two different repositories and I used commons-dbcp to make my application get data. It just seems the @transactional annotation on the service’s method doesn’t work. I don’t know what else I can do. Can I send you a piece of my code so you can tell me what I’m doing wrong?

    Reply
    • Hi,

      Can you add the source code of your service class and your application context configuration to Pastebin? After you have done this, just add the link here and I will take a look at it.

      Reply
      • Thank you for replying so soon.
        My application context file is in: http://pastebin.com/cXUZ663r

        Reply
        • My service is in: http://pastebin.com/q8vaV3t3
          and my controller (where the service is injected) is in: http://pastebin.com/McAEAyUF

          Thanks again

          Reply
          • I forgot to ask one thing:

            is your problem that the clear() method of the TransactionServiceImpl class doesn’t save anything to the database? If that is not the problem, what is it?

          • The problem is that the crear() method isn’t working as a transaction, because when the call for the save method of the second repository throws an exception, there is no rollback of data saved through the call for the save method in the first repository.

          • Where do you you configure the classpath scanning for service classes? Move this <context-scan/> element to the application context configuration file which you added to Pastebin (and remove it from the old file). Also, let me know if this did the trick.

  • Thanks for your great post.
    I am trying to configure Spring JPA.
    I have some questions.
    The DataJPAExampleInitializer isn’t loading.
    Do I need to configure something at web.xml?
    I am using Eclipse, Tomcat 7.
    Thanks very much!

    Reply
    • You don’t need the web.xml file anymore as long as you deploy the example application to a servlet container which supports the servlet 3.x API (Tomcat 7 supports it).

      Are you trying to deploy the war file to Tomcat 7 or are you trying to start the application in Eclipse by using its Tomcat support?

      Reply
  • Hi Petri,

    I discoverd your site a few days ago and I love it. It’s amazing.
    After reading your article I decided to convert the xml application configuration files to Java based configuration but I’m encountering a problem with the entityManager.

    My goal is to access to the Derby database of embedded glassfish with Spring Data JPA. It used to work well with the xml files (persistence + web)

    I posted my question on StackOverFlow. Could you have a look please ? I’ve spent hours unsucessfully.
    http://stackoverflow.com/questions/23857114/spring-java-config-error-creating-bean-with-name-entitymanagerfactory-defined

    Could you explain the pros and cons of the entityManager as described in the doc
    http://docs.spring.io/spring/docs/4.0.5.RELEASE/spring-framework-reference/htmlsingle/#orm-jpa-setup-jndi
    Obtaining an EntityManagerFactory from JNDI
    LocalContainerEntityManagerFactoryBean

    Thank you !
    Marc

    Reply
    • Hi Marc,

      Did the answer given to your StackOverflow question solve your problem?

      About your second question: I think the answers of this StackOverflow question answers to your question. Also, pay attention to these tips given in the Spring Framework Reference Manual:

      • Use the LocalEntityManagerFactoryBean in simple deployment environments such as stand-alone applications and integration tests.
      • Obtain the EntityManagerFactory from JNDI when deploying to a Java EE 5 server. Check your server’s documentation on how to deploy a custom JPA provider into your server, allowing for a different provider than the server’s default.
      • Use the LocalContainerEntityManagerFactoryBean for full JPA capabilities in a Spring-based application environment. This includes web containers such as Tomcat as well as stand-alone applications and integration tests with sophisticated persistence requirements.

      If you read this section of the Spring Framework Reference Manual, you will notice that the pros and cons of each approach are described in it.

      I hope that this answered to your question.

      Reply
      • A little late but… thank you for your help.
        Keep blogging and making tutorials :-)
        Marc

        Reply
        • You are welcome!

          Reply
  • Hi Petri,

    I can’t understand what do with the pom.xml . I do mvn install but generated is not a project structure but only a target directory.

    Where do I place ApplicationContext.java next?

    Reply
    • Hi Mo,

      if you use the default directory layout of Maven, you have to put your source code to the src/main/java directory (you should of course separate them to packages). Have you checked out the example application of this blog post? If not, I suggest that you take a look at it.

      Reply
  • Hi Petri,
    Excellent Tutorials.
    I am new to SpringData JPA,I refer your tutorials,I create a tutorial-part-one project using IntelliJ IDE & Maven, Maven is build Successfully,But whenever i run through tomcat server I did not get any out put where i mistake, please help me

    Thank you!,
    Sanjeev K

    Reply
  • Hi Petri,

    Now I have performance problem when I load application it takes 9-10seconds where server itself
    takes not more than 2, 2.5 seconds. How to load spring jars faster ?
    Thank you.
    Boris

    Reply
    • Is the “extra time” spend on loading the Spring application context or does it look like that the server is not doing anything?

      If the log file shows that the extra time is spend when the server loads the Spring application context, you cannot really do anything to it (I will come back to this later).

      On the other hand, if the server appears to be idle, it is probably scanning the jar files of your application. If this is the case, check out this wiki page found from the Jetty wiki: Avoid Slow Deployment.

      If you don’t want to start your server every time when you make a minor change to your application, you can avoid it by using one of these products (there might be others too):

      • JRebel is a commercial product that will help you to be more productive because it can reload Java classes at runtime.
      • Spring Loaded is an open source JVM agent that can reload Java classes at runtime.
      Reply

Leave a Comment