Spring Data JPA完全指南:从入门到精通的Java持久层框架教程
Spring Data JPA详解(第1部分,共4部分)
Spring Data JPA 是 Spring Data 家族的一部分。Spring Data 使得创建使用新的数据访问方式(如非关系型数据库、映射减少框架、云服务以及高级关系型数据库支持)的基于 Spring 的应用程序变得更加容易。本文将讨论 Spring Data JPA,并且还会介绍一个 Spring Data JPA 示例应用程序。
Spring Data JPA的核心功能
Spring Data JPA提供的一些很酷的功能有:
- 使用Spring和JPA创建和支持存储库
- 支持QueryDSL和JPA查询
- 对域类进行审计
- 支持批量加载、排序、动态查询
- 支持实体的XML映射
- 通过使用CrudRepository减少通用CRUD操作的代码量
何时使用Spring Data JPA?
我认为,如果你需要快速创建一个主要用于CRUD操作的基于JPA的存储库层,并且不想创建抽象DAO、实现接口,那么Spring Data JPA是一个不错的选择。
Spring Data JPA示例
在我们的Spring Data JPA示例中,我们将创建一个连接到Postgresql数据库的RESTful Web服务。我们将实现基本的CRUD操作,并在我们已经创建的示例数据上进行操作。
示例数据
使用以下查询在PostgreSQL数据库中创建表并添加一些测试数据。
create table people (
id serial not null primary key,
first_name varchar(20) not null,
last_name varchar(20) not null,
age integer not null
);
insert into people (id, first_name, last_name, age) values
(1, 'Vlad', 'Boyarskiy', 21),
(2,'Oksi', ' Bahatskaya', 30),
(3,'Vadim', ' Vadimich', 32);
Maven 项目结构

Maven依赖
我们需要为我们的Spring Data JPA示例项目添加以下依赖项。
- PostgreSQL:PostgreSQL Java驱动程序。
- Spring-core,spring-context:Spring框架核心依赖。
- Spring-webmvc,jackson-databind:用于Spring REST应用程序。
- Spring-data-jpa,hibernate-entitymanager:用于Spring Data JPA和Hibernate支持。
以下是最终的pom.xml构建文件内容。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.Olivia</groupId>
<artifactId>springData</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Spring Data JPA Maven Webapp</name>
<url>https://maven.apache.org</url>
<properties>
<spring.framework>4.3.0.RELEASE</spring.framework>
<postgres.version>42.1.4</postgres.version>
<serializer.version>2.8.1</serializer.version>
<spring.data>1.3.4.RELEASE</spring.data>
<hibernate.manager>4.2.5.Final</hibernate.manager>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring.data}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.manager}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${serializer.version}</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
</build>
</project>
Spring 配置类
这是文章《春天的数据JPA》的第2部分(共4部分)。
package com.Olivia.spring.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.ejb.HibernatePersistence;
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.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.Olivia.spring.repository")
@PropertySource("classpath:database.properties")
public class DataConfig {
private final String PROPERTY_DRIVER = "driver";
private final String PROPERTY_URL = "url";
private final String PROPERTY_USERNAME = "user";
private final String PROPERTY_PASSWORD = "password";
private final String PROPERTY_SHOW_SQL = "hibernate.show_sql";
private final String PROPERTY_DIALECT = "hibernate.dialect";
@Autowired
Environment environment;
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lfb = new LocalContainerEntityManagerFactoryBean();
lfb.setDataSource(dataSource());
lfb.setPersistenceProviderClass(HibernatePersistence.class);
lfb.setPackagesToScan("com.Olivia.spring.model");
lfb.setJpaProperties(hibernateProps());
return lfb;
}
@Bean
DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl(environment.getProperty(PROPERTY_URL));
ds.setUsername(environment.getProperty(PROPERTY_USERNAME));
ds.setPassword(environment.getProperty(PROPERTY_PASSWORD));
ds.setDriverClassName(environment.getProperty(PROPERTY_DRIVER));
return ds;
}
Properties hibernateProps() {
Properties properties = new Properties();
properties.setProperty(PROPERTY_DIALECT, environment.getProperty(PROPERTY_DIALECT));
properties.setProperty(PROPERTY_SHOW_SQL, environment.getProperty(PROPERTY_SHOW_SQL));
return properties;
}
@Bean
JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
- @Configuration: 这个Spring注解表明它是一个配置类。
- @EnableTransactionManagement: 这个注解允许用户在应用程序中使用事务管理。
- @EnableJpaRepositories(“com.Olivia.spring.repository”): 指明仓库类所在的位置。
- @PropertySource(“classpath:database.properties”): 表示我们在类路径中有一个属性文件。这个文件中的值将被注入到环境变量中。database.properties文件的内容如下所示:
driver=org.postgresql.Driver url=jdbc:postgresql://127.0.0.1:5432/postgres user=postgres password=postgres hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect hibernate.show_sql=true
- 要使用Spring Data,首先我们必须配置DataSource bean。然后我们需要配置LocalContainerEntityManagerFactoryBean bean。我们需要这个bean来控制实体。在这个bean中,你必须指定持久化提供者,在我们的例子中是HibernatePersistence。
- 下一步是配置事务管理的bean。在我们的例子中是JpaTransactionManager。请注意,不配置事务管理器我们就不能使用@Transactional注解。
通过AppInitializer和WebConfig类来配置我们的应用程序为web应用程序,而不需要使用web.xml文件。
模型类
package com.Olivia.spring.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "people")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "age")
private Integer age;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
public Person() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Person{" + "id=" + id + ", age=" + age + ", firstName='" + firstName + '\'' + ", lastName='" + lastName
+ '\'' + '}';
}
}
在这里,我们有一些新的批注。让我们更详细地谈谈它们。
- @Entity: This annotation allows entity manager to use this class and puts it in context.
- @Table(name = “people”): associates a class with a table in the database.
- @Id: says that this field is the primary key.
- @GeneratedValue(strategy = GenerationType.IDENTITY): Defines the strategy for generating the primary key.
- @Column(name = “age”): denotes a column in the database with which this field will be associated.
Spring Data JPA 仓库下一步是创建JPA存储库。
package com.Olivia.spring.repository;
import org.springframework.data.repository.CrudRepository;
import com.Olivia.spring.model.Person;
import java.util.List;
public interface PersonRepository<P> extends CrudRepository<Person, Long> {
List<Person> findByFirstName(String firstName);
}
package com.Olivia.spring.repository;
import org.springframework.data.repository.CrudRepository;
import com.Olivia.spring.model.Person;
import java.util.List;
public interface PersonRepository<P> extends CrudRepository<Person, Long> {
List<Person> findByFirstName(String firstName);
}
通过继承CrudRepository,我们可以调用许多方法而无需自己实现。其中一些方法包括:
- save
- findOne
- exists
- findAll
- count
- delete
- deleteAll
我们也可以定义自己的方法。这些方法名应该使用特殊的关键字,如“find”、“order”,加上变量的名称。Spring Data JPA的开发人员已经试图考虑到可能需要的大部分选项。在我们的示例中,findByFirstName(String firstName)方法返回表中字段first_name等于firstName的所有条目。这是Spring Data JPA的一个最重要的特性,因为它减少了很多样板代码。而且出错的机会较少,因为这些Spring方法已经被许多已经使用它们的项目充分测试过。
春季服务班既然我们的Spring Data JPA代码已经准备就绪,下一步就是创建服务类并定义我们将用于操作数据库表的方法。
package com.Olivia.spring.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.Olivia.spring.model.Person;
import com.Olivia.spring.repository.PersonRepository;
@Service
public class PersonService {
@Autowired
PersonRepository<Person> personRepository;
@Transactional
public List<Person> getAllPersons() {
return (List<Person>) personRepository.findAll();
}
@Transactional
public List<Person> findByName(String name) {
return personRepository.findByFirstName(name);
}
@Transactional
public Person getById(Long id) {
return personRepository.findOne(id);
}
@Transactional
public void deletePerson(Long personId) {
personRepository.delete(personId);
}
@Transactional
public boolean addPerson(Person person) {
return personRepository.save(person) != null;
}
@Transactional
public boolean updatePerson(Person person) {
return personRepository.save(person) != null;
}
}
package com.Olivia.spring.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.Olivia.spring.model.Person;
import com.Olivia.spring.repository.PersonRepository;
@Service
public class PersonService {
@Autowired
PersonRepository<Person> personRepository;
@Transactional
public List<Person> getAllPersons() {
return (List<Person>) personRepository.findAll();
}
@Transactional
public List<Person> findByName(String name) {
return personRepository.findByFirstName(name);
}
@Transactional
public Person getById(Long id) {
return personRepository.findOne(id);
}
@Transactional
public void deletePerson(Long personId) {
personRepository.delete(personId);
}
@Transactional
public boolean addPerson(Person person) {
return personRepository.save(person) != null;
}
@Transactional
public boolean updatePerson(Person person) {
return personRepository.save(person) != null;
}
}
@Transactional注解表示该方法将在事务中执行。Spring将负责事务管理。
Spring控制器类
这是文章《Spring Data JPA入门指南》的第4部分(共4部分)。
内容片段: 最后一步是创建控制器类,将我们的API暴露给外部世界。
package com.Olivia.spring.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.Olivia.spring.model.Person;
import com.Olivia.spring.services.PersonService;
@RestController
public class PersonController {
@Autowired
PersonService personService;
@RequestMapping(value = "/person/{id}", method = RequestMethod.GET)
public @ResponseBody Person getAllUsers(@PathVariable Long id) {
return personService.getById(id);
}
@RequestMapping(value = "/personByName/{name}", method = RequestMethod.GET)
public List<Person> getPersoneByName(@PathVariable String name) {
return personService.findByName(name);
}
@RequestMapping(value = "/person", method = RequestMethod.GET)
public List<Person> getAll() {
return personService.getAllPersons();
}
@RequestMapping(value = "/person/{id}", method = RequestMethod.DELETE)
public HttpStatus deletePersnone(@PathVariable Long id) {
personService.deletePerson(id);
return HttpStatus.NO_CONTENT;
}
@RequestMapping(value = "/person", method = RequestMethod.POST)
public HttpStatus insertPersone(@RequestBody Person person) {
return personService.addPerson(person) ? HttpStatus.CREATED : HttpStatus.BAD_REQUEST;
}
@RequestMapping(value = "/person", method = RequestMethod.PUT)
public HttpStatus updatePerson(@RequestBody Person person) {
return personService.updatePerson(person) ? HttpStatus.ACCEPTED : HttpStatus.BAD_REQUEST;
}
}
Spring Data JPA 测试
只需将项目构建并部署到您最喜欢的servlet容器(如Tomcat)中。以下图片显示了一些API调用的响应。
Spring Data JPA 读取全部数据

通过名称获取Spring Data JPA数据

使用Spring Data JPA进行创建

Spring Data JPA 更新数据

Spring Data JPA 删除数据

下载Spring Data JPA示例项目
参考资料:Spring官方网站