Spring Boot 2.x 集成Spring Data JPA 教程(上卷)

当你看到了我这篇博文,那么我想你应该已经知道 Spring Data JPA 在如今的互联网开发中使用非常频繁。

所以今天这篇博文主要探讨学习Spring Boot 2.x 中如何集成Spring Data JPA.

在写代码之前,请让我们带着这三个问题去学习。

  1. 为什么使用Spring Data JPA?
  2. 它解决了一个什么问题?
  3. Spring Data JPA 如何使用?

0x01 为什么使用Spring Data JPA?

1.1 什么是Spring Data JPA?

JPA全称Java Persistence API,即Java持久化API
Spring Data JPA 是Spring Data 家族的一员。

1.2 Spring Data又是什么?

Spring 为了简化数据持久化而开发的模块。
它简化了对关系型数据库和非关系型数据库的访问。

1.3 Spring Data 家族有哪些模块?

Spring Data 家族包括以下模块:
Spring Boot 2.x 集成Spring Data JPA 教程(上卷)_第1张图片
通过上图,我们可以看到我们熟悉的JDBC,Redis,MongoDB,JPA。

  • Spring-Data-JDBC
  • Spring-Data-JPA
  • Spring-Data-MongoDB
  • Spring-Data-Redis

Spring 针对我们程序员经常使用的JDBC,JPA,MongoDB,Redis 做了简化开发。
接下来的日子我会针对以上这几个常用的模块抽时间一一讲解。

0x02 Spring Data JPA 解决了什么问题?

好了,扯了那么多废话,现在让我们回归今天的主角 ————Spring Data JPA。

那么Spring Data JPA 是个什么鬼?它到底解决了什么问题?

Spring Data JPA 本质是定义了一套通用数据访问层接口,具体的实现由Hibernate来完成。

0x03 如何使用Spring Data JPA?

3.1 环境搭建

  • JDK: 1.8+
  • IDE 工具:Spring Tools 4 for Eclipse
  • 可选:IDE常用配置:星云STS 常用配置
  • 项目依赖管理:Maven 3.2+

3.2 编码实战

方式一:直接下载

https://github.com/spring-guides/gs-accessing-data-jpa/archive/master.zip

方式二:Spring官方Demo Git 下载

git clone https://github.com/spring-guides/gs-accessing-data-jpa.git

方式三:Spring 官网类库直接导入IDE(推荐)

1 打开IDE, 右键--------> New -------->Import Spring Getting Started Content
Spring Boot 2.x 集成Spring Data JPA 教程(上卷)_第2张图片
2.选中Accessing Data JPA,默认配置如下:
Spring Boot 2.x 集成Spring Data JPA 教程(上卷)_第3张图片

推荐这种学习方式
initial 勾选会创建一个空的项目,complete 会创建一个已完成的项目

3.点击Finish 完成后,将会看到这个
在这里插入图片描述
4.展开gs-accessing-data-jpa-initial 项目,可以看到项目结构如下
Spring Boot 2.x 集成Spring Data JPA 教程(上卷)_第4张图片
5.我们打开pom.xml 可以看到如下内容:



    4.0.0

    org.springframework
    gs-accessing-data-jpa
    0.1.0

    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.5.RELEASE
    

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
            com.h2database
            h2
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



  1. 然后假如我们需要保存一个Customer 对象,定义内容如下:

Customer.java

package hello;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Customer {

	@Id
       @GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;
	private String firstName;
	private String lastName;
	
	protected Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%d, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }
}

@Entity 表明这是一个JPA持久化类对象 由于缺少@Table注解,因此假定此实体将映射到名为Customer的表。
@Id 和@GeneratedValue(strategy=GenerationType.AUTO) 标识这是一个自增长ID
现在我们这个Customer对象有了这些属性,id,firstName,lastName.
我们也有了两个构造方法,默认构造函数仅为JPA而存在。 我们不会直接使用它,因此它被指定为受保护的用protected 关键字标识。
另一个构造函数是我们将用于创建要保存到数据库的Customer实例的构造函数。 为了让代码看起来简洁,这里省略了getter 和setter 方法,但是不影响使用。

7.创建一个简单的查询
我们创建一个接口类CustomerRepository.java

package hello;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

public interface CustomerRepository extends CrudRepository{

	List findByLastName(String lastName);
}

CustomerRepository扩展了CrudRepository接口。
它使用的实体和ID类型Customer和Long在CrudRepository的通用参数中指定。
通过扩展CrudRepository,CustomerRepository继承了几种使用Customer持久性的方法,包括用于保存,删除和查找Customer实体的方法。
Spring Data JPA还允许我们通过简单地声明其方法签名来定义其他查询方法。
对于CustomerRepository,它使用findByLastName()方法显示。
在典型的Java应用程序中,您希望编写一个实现CustomerRepository的类。 但这就是使Spring Data JPA如此强大的原因:我们不必编写存储库接口的实现。 Spring Data JPA在您运行应用程序时动态创建实现

Spring Data JPA如此强大的原因:我们不必编写存储库接口的实现。 Spring Data JPA在您运行应用程序时动态创建实现

8.创建应用程序启动类Application.java

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

	private static final Logger log = LoggerFactory.getLogger(Application.class);

	public static void main(String[] args) {
		SpringApplication.run(Application.class);
	}
	
	@Bean
	public CommandLineRunner demo(CustomerRepository repository) {
		return (args) -> {
			// save a couple of customers
			repository.save(new Customer("Jack", "Bauer"));
			repository.save(new Customer("Chloe", "O'Brian"));
			repository.save(new Customer("Kim", "Bauer"));
			repository.save(new Customer("David", "Palmer"));
			repository.save(new Customer("Michelle", "Dessler"));

			// fetch all customers
			log.info("Customers found with findAll():");
			log.info("-------------------------------");
			for (Customer customer : repository.findAll()) {
				log.info(customer.toString());
			}
			log.info("");

			// fetch an individual customer by ID
			repository.findById(1L)
				.ifPresent(customer -> {
					log.info("Customer found with findById(1L):");
					log.info("--------------------------------");
					log.info(customer.toString());
					log.info("");
				});

			// fetch customers by last name
			log.info("Customer found with findByLastName('Bauer'):");
			log.info("--------------------------------------------");
			repository.findByLastName("Bauer").forEach(bauer -> {
				log.info(bauer.toString());
			});
			// for (Customer bauer : repository.findByLastName("Bauer")) {
			// 	log.info(bauer.toString());
			// }
			log.info("");
		};
	}
}

@SpringBootApplication是一个方便的注解,添加了以下所有内容:

  • @Configuration将类标记为应用程序上下文的bean定义源。
  • @EnableAutoConfiguration告诉Spring Boot根据类路径设置,其他bean和各种属性设置开始添加bean。
  • 通常你会为Spring MVC应用程序添加@EnableWebMvc,但Spring Boot会在类路径上看到spring-webmvc时自动添加它。 这会将应用程序标记为Web应用程序并激活关键行为,例如设置DispatcherServlet。
  • @ComponentScan告诉Spring在hello包中寻找其他组件,配置和服务,允许它找到controllers控制器。

main()方法使用Spring Boot的SpringApplication.run()方法来启动应用程序。 您是否注意到没有一行XML?也没有web.xml文件。 此Web应用程序是100%纯Java,我们无需处理配置任何管道或基础结构。

Application包含一个main()方法,它通过一些测试放置CustomerRepository。 首先,它从Spring应用程序上下文中获取CustomerRepository。 然后它保存了一些Customer对象,演示了save()方法并设置了一些要处理的数据。 接下来,它调用findAll()从数据库中获取所有Customer对象。 然后它调用findOne()以通过其ID获取单个Customer。 最后,它调用findByLastName()来查找姓氏为“Bauer”的所有客户。

默认情况下,Spring Boot将启用JPA存储库支持并查看@SpringBootApplication所在的包(及其子包)。
如果您的配置包含位于包中的JPA存储库接口定义,则可以使用@EnableJpaRepositories及其类型安全的basePackageClasses
= MyRepository.class参数指出备用包。

运行主方法后可以看到


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.5.RELEASE)

2018-12-15 11:49:45.689  INFO 8704 --- [           main] hello.Application                        : Starting Application on DESKTOP-P6BK6E2 with PID 8704 (C:\Users\fairy\Documents\SpringBootWorkSpace\gs-accessing-data-jpa-initial\target\classes started by fairy in C:\Users\fairy\Documents\SpringBootWorkSpace\gs-accessing-data-jpa-initial)
2018-12-15 11:49:45.693  INFO 8704 --- [           main] hello.Application                        : No active profile set, falling back to default profiles: default
2018-12-15 11:49:45.729  INFO 8704 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4c40b76e: startup date [Sat Dec 15 11:49:45 CST 2018]; root of context hierarchy
2018-12-15 11:49:47.602  INFO 8704 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2018-12-15 11:49:47.943  INFO 8704 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2018-12-15 11:49:48.211  INFO 8704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2018-12-15 11:49:48.288  INFO 8704 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
	name: default
	...]
2018-12-15 11:49:48.615  INFO 8704 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.2.17.Final}
2018-12-15 11:49:48.617  INFO 8704 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2018-12-15 11:49:48.720  INFO 8704 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2018-12-15 11:49:48.964  INFO 8704 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2018-12-15 11:49:49.630  INFO 8704 --- [           main] o.h.t.schema.internal.SchemaCreatorImpl  : HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@70f31322'
2018-12-15 11:49:49.635  INFO 8704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2018-12-15 11:49:50.386  INFO 8704 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-12-15 11:49:50.388  INFO 8704 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-12-15 11:49:50.394  INFO 8704 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2018-12-15 11:49:50.408  INFO 8704 --- [           main] hello.Application                        : Started Application in 5.004 seconds (JVM running for 6.221)
2018-12-15 11:49:50.585  INFO 8704 --- [           main] hello.Application                        : Customers found with findAll():
2018-12-15 11:49:50.585  INFO 8704 --- [           main] hello.Application                        : -------------------------------
2018-12-15 11:49:50.748  INFO 8704 --- [           main] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
2018-12-15 11:49:50.891  INFO 8704 --- [           main] hello.Application                        : Customer[id=1, firstName='Jack', lastName='Bauer']
2018-12-15 11:49:50.891  INFO 8704 --- [           main] hello.Application                        : Customer[id=2, firstName='Chloe', lastName='O'Brian']
2018-12-15 11:49:50.891  INFO 8704 --- [           main] hello.Application                        : Customer[id=3, firstName='Kim', lastName='Bauer']
2018-12-15 11:49:50.891  INFO 8704 --- [           main] hello.Application                        : Customer[id=4, firstName='David', lastName='Palmer']
2018-12-15 11:49:50.891  INFO 8704 --- [           main] hello.Application                        : Customer[id=5, firstName='Michelle', lastName='Dessler']
2018-12-15 11:49:50.891  INFO 8704 --- [           main] hello.Application                        : 
2018-12-15 11:49:50.904  INFO 8704 --- [           main] hello.Application                        : Customer found with findById(1L):
2018-12-15 11:49:50.904  INFO 8704 --- [           main] hello.Application                        : --------------------------------
2018-12-15 11:49:50.904  INFO 8704 --- [           main] hello.Application                        : Customer[id=1, firstName='Jack', lastName='Bauer']
2018-12-15 11:49:50.904  INFO 8704 --- [           main] hello.Application                        : 
2018-12-15 11:49:50.904  INFO 8704 --- [           main] hello.Application                        : Customer found with findByLastName('Bauer'):
2018-12-15 11:49:50.904  INFO 8704 --- [           main] hello.Application                        : --------------------------------------------
2018-12-15 11:49:50.943  INFO 8704 --- [           main] hello.Application                        : Customer[id=1, firstName='Jack', lastName='Bauer']
2018-12-15 11:49:50.943  INFO 8704 --- [           main] hello.Application                        : Customer[id=3, firstName='Kim', lastName='Bauer']
2018-12-15 11:49:50.943  INFO 8704 --- [           main] hello.Application                        : 
2018-12-15 11:49:50.945  INFO 8704 --- [       Thread-3] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@4c40b76e: startup date [Sat Dec 15 11:49:45 CST 2018]; root of context hierarchy
2018-12-15 11:49:50.950  INFO 8704 --- [       Thread-3] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2018-12-15 11:49:50.951  INFO 8704 --- [       Thread-3] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans
2018-12-15 11:49:50.953  INFO 8704 --- [       Thread-3] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2018-12-15 11:49:50.954  INFO 8704 --- [       Thread-3] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed drop of schema as part of SessionFactory shut-down'
2018-12-15 11:49:50.960  INFO 8704 --- [       Thread-3] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2018-12-15 11:49:50.963  INFO 8704 --- [       Thread-3] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

3.2 参考文档

参考官方指南英文版:https://spring.io/guides/gs/accessing-data-jpa/

更多Spring官方学习指南 https://spring.io/guides

你可能感兴趣的:(Spring,Data,JPA,Spring,Boot,2.x)