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?
I would say that if you need to quickly create a JPA-based repository layer that is mainly for CRUD operations, and you do not want to create abstract DAO, implementing interfaces, Spring Data JPA is a good choice.
Spring Data JPA 示例
對於我們的Spring Data JPA示例,我們將創建一個連接到Postgresql數據庫的RESTful Web服務。我們將實現基本的CRUD操作,並在我們已經創建的示例數據上進行工作。
Spring JAP示例樣本數據
使用下面的查詢在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);
Spring Data JPA Maven項目結構
下面的圖像顯示了最終的Spring JPA項目結構。我們稍後將詳細研究每個組件。
Spring Data JPA Maven依賴項
我們需要為我們的Spring Data JPA示例項目添加以下依賴項。
postgresql
:Postgresql Java驅動程式。spring-core
,spring-context
: Spring Framework 核心依賴。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.journaldev</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 配置類
package com.journaldev.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.journaldev.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.journaldev.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.journaldev.spring.repository")
: 指示存放 repositories 類別的位置。 -
@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.journaldev.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:此注解允许实体管理器使用此类,并将其放入上下文中。
- @Table(name = “people”):将类与数据库中的表关联起来。
@Id
:表示此字段是主键。@GeneratedValue(strategy = GenerationType.IDENTITY)
:定義生成主鍵的策略。@Column(name = "age")
:表示數據庫中的列,該字段將與之關聯。
Spring Data JPA Repository
下一步是創建JPA存儲庫。
package com.journaldev.spring.repository;
import org.springframework.data.repository.CrudRepository;
import com.journaldev.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 Service Class
現在我們的 Spring Data JPA 代碼已經準備好,下一步是創建服務類並定義我們將與數據庫表一起使用的方法。
package com.journaldev.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.journaldev.spring.model.Person;
import com.journaldev.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 Controller Class
最後一步是創建控制器類,將我們的 API 暴露給外界。
package com.journaldev.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.journaldev.spring.model.Person;
import com.journaldev.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 刪除
春季数据JPA示例教程到此为止。您可以从以下链接下载最终项目。
参考: 官方网站
Source:
https://www.digitalocean.com/community/tutorials/spring-data-jpa