A Guide to JPA with Spring – 使用Spring的JPA指南

最后修改: 2013年 12月 18日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

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

本教程展示了如何使用Hibernate作为持久性提供者来设置Spring与JPA

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

有关使用基于Java的配置和项目的基本Maven pom来设置Spring上下文的逐步介绍,请参阅这篇文章

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.

我们将从在Spring Boot项目中设置JPA开始。然后我们将研究一下如果我们有一个标准的Spring项目,我们需要的全部配置。

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

这里有一个关于用Spring 4设置Hibernate 4的视频(建议以全1080p观看)。

2. JPA in Spring Boot

2.Spring Boot中的JPA

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.

Spring Boot项目的目的是使创建Spring应用程序变得更快、更容易。这是通过使用启动器和自动配置各种Spring功能来实现的,JPA就是其中之一。

2.1. Maven Dependencies

2.1.Maven的依赖性

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

要在Spring Boot应用程序中启用JPA,我们需要 spring-boot-starter spring-boot-starter-data-jpa 依赖。

<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-core.

spring-boot-starter包含Spring JPA的必要自动配置。此外,spring-boot-starter-jpa项目引用了所有必要的依赖,例如hibernate-core

2.2. Configuration

2.2.配置

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将Hibernate配置为默认的JPA提供者,因此不再需要定义entityManagerFactorybean,除非我们想定制它。

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.

Spring Boot还可以自动配置dataSourcebean,这取决于我们使用的数据库。如果是H2HSQLDBApache Derby类型的内存数据库,如果classpath上存在相应的数据库依赖,Boot将自动配置DataSource

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:

例如,如果我们想在Spring Boot JPA应用程序中使用内存H2数据库,我们只需在pom.xml文件中添加h2依赖。

<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 if we want to customize it.

这样,我们就不需要定义dataSource bean,但如果我们想定制它,我们可以这样做。

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.

如果我们想在MySQL数据库中使用JPA,我们需要mysql-connector-java依赖。我们还需要定义DataSource配置。

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

我们可以在@Configuration类中或通过使用标准的Spring Boot属性来做到这一点。

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

Java配置看起来与标准Spring项目中的配置相同。

@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为前缀的属性。

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.

Spring Boot会根据这些属性自动配置一个数据源。

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

另外,在Spring Boot 1中,默认的连接池是Tomcat,但在Spring Boot 2中已经改为HikariCP

We have more examples of configuring JPA in Spring Boot in the GitHub project.

我们在GitHub项目中拥有更多在Spring Boot中配置JPA的例子。

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

我们可以看到,如果我们使用Spring Boot,基本的JPA配置是相当简单的。

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

然而,如果我们有一个标准的Spring项目,我们需要更明确的配置,使用Java或XML。这就是我们在接下来的章节中要关注的内容。

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

3.在非Boot项目中用Java配置JPA Spring

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

要在Spring项目中使用JPA,我们需要设置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.

这是配置的主要部分,我们可以通过一个Spring工厂Bean来完成它。这可以是更简单的LocalEntityManagerFactoryBean更灵活的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:

我们还需要明确地定义我们上面使用的DataSourcebean

@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 is the additional Hibernate properties and the TransactionManager and exceptionTranslation beans:

配置的最后部分是额外的Hibernate属性以及TransactionManagerexceptionTranslationBean。

@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. JPA Spring Configuration With XML

4.使用XML的JPA Spring配置

Next, let’s see the same Spring configuration with XML:

接下来,让我们看看同样的Spring配置与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.

在XML和基于Java的新配置之间有一个相对较小的区别。也就是说,在XML中,对另一个Bean的引用可以指向该Bean或该Bean的一个Bean工厂。

But in Java, 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:

但是在Java中,由于类型不同,编译器不允许这样做,所以EntityManagerFactory首先从其Bean工厂检索,然后传递给事务管理器。

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

5. Going Full XML-less

5.完全无XML

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.

通常,JPA通过META-INF/persistence.xml文件定义持久化单元。从Spring 3.1开始,不再需要persistence.xmlLocalContainerEntityManagerFactoryBean现在支持一个packagesToScan属性,可以指定要扫描@Entity类的包。

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

这个文件是我们需要删除的最后一块XML。我们现在可以在没有XML的情况下完全设置JPA了。

We would usually specify JPA properties in the persistence.xml file.

我们通常会在persistence.xml文件中指定JPA属性。

Alternatively, we can add the properties directly to the entity manager factory bean:

另外,我们也可以直接将这些属性添加到实体管理器工厂Bean中。

factoryBean.setJpaProperties(this.additionalProperties());

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

顺便提一下,如果Hibernate是持久化提供者,这也是指定Hibernate特定属性的方法。

6. The Maven Configuration

6.Maven的配置

In addition to the Spring Core and persistence dependencies — shown 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:

除了Spring Core和持久性依赖–在Spring with Maven教程中详细显示–我们还需要在项目中定义JPA和Hibernate以及一个MySQL连接器。

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>5.2.17.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 data source, but any Hibernate-supported database will do.

请注意,这里包括了MySQL的依赖性,作为一个例子。我们需要一个驱动程序来配置数据源,但任何支持Hibernate的数据库都可以。

7. Conclusion

7.结论

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

本教程说明了如何在Spring Boot和标准Spring应用程序中配置JPA与Hibernate

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

一如既往,本文介绍的代码可在GitHub上获得over。