春天的数据JPA
Spring Data JPA 是 Spring Data 家族的一部分。Spring Data 使得创建使用新的数据访问方式(如非关系型数据库、映射减少框架、云服务以及高级关系型数据库支持)的基于 Spring 的应用程序变得更加容易。本文将讨论 Spring Data JPA,并且还会介绍一个 Spring Data JPA 示例应用程序。
春季数据 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);
Spring Data JPA Maven 项目结构
Spring Data JPA的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 配置类
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: this spring annotation says that it is configuration class.
- @EnableTransactionManagement: this annotation allows users to use transaction management in application.
- @EnableJpaRepositories(“com.Olivia.spring.repository”): indicates where the repositories classes are present.
- @PropertySource(“classpath:database.properties”): says that we have property file in our classpath. The values from this file will be injected into environment variable. The contents of the database.properties file are shown below.
driver=org.postgresql.Driver
url=jdbc:postgresql://127.0.0.1:5432/postgres
user=postgres
password=postgreshibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect
hibernate.show_sql=true - For using Spring Data, first of all we have to configure DataSource bean. Then we need to configure LocalContainerEntityManagerFactoryBean bean. We need this bean to control the entities. In this beans, you must specify the persistence provider i.e. HibernatePersistence in our case.
- The next step is to configure bean for transaction management. In our example it’s JpaTransactionManager. Note that without configuring transaction manager we can’t use @Transactional annotation.
通过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);
}
通过继承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;
}
}
@Transactional注解表示该方法将在事务中执行。Spring将负责事务管理。
Spring控制器类
最后一步是创建控制器类,将我们的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调用的响应。
春季数据JPA读取全部
通过名称获取Spring Data JPA
使用Spring Data JPA进行创建
Spring Data JPA 更新.
Spring Data JPA 删除
下载Spring Data JPA示例项目
参考资料:官方网站