03_Spring Boot 使用 Spring-data-jpa 简化数据访问层

1、pom.xml配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.linjb</groupId>

<artifactId>springboot-spring-data-jpa</artifactId>

<packaging>war</packaging>

<version>0.0.1-SNAPSHOT</version>

<name>springboot-spring-data-jpa Maven Webapp</name>

<url>http://maven.apache.org</url>

<!-- Spring Boot 启动父依赖 -->

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.3.3.RELEASE</version>

</parent>

<dependencies>

<!-- Spring Boot web依赖 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>io.springfox</groupId>

<artifactId>springfox-swagger2</artifactId>

<version>2.2.2</version>

</dependency>

<dependency>

<groupId>io.springfox</groupId>

<artifactId>springfox-swagger-ui</artifactId>

<version>2.2.2</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<!-- MySQL 连接驱动依赖 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

</dependencies>

<build>

<finalName>springboot-spring-data-jpa</finalName>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<configuration>

<source>1.8</source>

<target>1.8</target>

<encoding>UTF-8</encoding>

</configuration>

</plugin>

</plugins>

</build>

</project>

 

2、application.properties 配置

在 application.properties 中配置:数据库连接信息(如使用嵌入式数据库则不需要)、自动创建表结构的设置,例如使用 mysql 的情况如下:

## 数据源配置

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test_base_1?useUnicode=true&characterEncoding=utf-8

spring.datasource.username=root

spring.datasource.password=root

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

## Hibernate 的配置属性,其主要作用是:自动创建、更新、验证数据库表结构

spring.jpa.properties.hibernate.hbm2ddl.auto=update

spring.jpa.show-sql=true

spring.http.encoding.force=true

spring.http.encoding.charset=UTF-8

spring.http.encoding.enabled=true

server.tomcat.uri-encoding=UTF-8

 

注:spring.jpa.properties.hibernate.hbm2ddl.auto 是 hibernate 的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。该参数的几种配置如下:

1)、create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。

2)、create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。

3)、update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。

4)、validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

 

3、Model层

package com.linjb.model;

 

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

 

/**

* 政治面貌表模型

* @Copyright Copyright (C) 2019 linjb

* @author linjb

* @version 1.0

* @CreateDate 2019年2月3日下午6:12:14

*/

@Entity

public class PoliticalStatus {

 

@Id

@GeneratedValue

private Integer politicalStatusId;

@Column

private String politicalStatusName;

public Integer getPoliticalStatusId() {

return politicalStatusId;

}

public void setPoliticalStatusId(Integer politicalStatusId) {

this.politicalStatusId = politicalStatusId;

}

public String getPoliticalStatusName() {

return politicalStatusName;

}

public void setPoliticalStatusName(String politicalStatusName) {

this.politicalStatusName = politicalStatusName;

}

}

 

4、创建数据访问接口

针对 PoliticalStatus 实体创建对应的Repository接口实现对该实体的数据访问,如下代码:

package com.linjb.model;

 

import java.util.List;

 

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.Query;

import org.springframework.data.repository.query.Param;

 

public interface PoliticalStatusRepository extends JpaRepository<PoliticalStatus, Long>{

 

public PoliticalStatus findByPoliticalStatusId(Integer politicalStatusId);

public PoliticalStatus findByPoliticalStatusName(String politicalStatusName);

@Query("select politicalStatus from PoliticalStatus politicalStatus where politicalStatus.politicalStatusName like %:nn")

List<PoliticalStatus> fuzzyQueryByPoliticalStatusName(@Param("nn") String politicalStatusName);

}

 

在 Spring-data-jpa 中,只需要编写类似上面这样的接口就可实现数据访问。不再像我们以往编写了接口时候还需要自己编写接口实现类,直接减少了我们的文件清单。

下面对上面的 PoliticalStatusRepository 做一些解释,该接口继承自JpaRepository,通过查看JpaRepository接口的API文档,可以看到该接口本身已经实现了创建(save)、更新(save)、删除(delete)、查询(findAll、findOne)等基本操作的函数,因此对于这些基础操作的数据访问就不需要开发者再自己定义。

在我们实际开发中,JpaRepository接口定义的接口往往还不够或者性能不够优化,我们需要进一步实现更复杂一些的查询或操作。由于本文重点在spring boot中整合spring-data-jpa,在这里先抛砖引玉简单介绍一下spring-data-jpa中让我们兴奋的功能,后续再单独开篇讲一下spring-data-jpa中的常见使用。

在上例中,我们可以看到下面两个函数:

public PoliticalStatus findByPoliticalStatusId(Integer politicalStatusId);

public PoliticalStatus findByPoliticalStatusName(String politicalStatusName);

它们分别实现了按 politicalStatusId 查询 PoliticalStatus 实体和按politicalStatusName查询User实体,可以看到我们这里没有任何类SQL语句就完成了两个条件查询方法。这就是Spring-data-jpa的一大特性:通过解析方法名创建查询。

除了通过解析方法名来创建查询外,它也提供通过使用@Query 注解来创建查询,您只需要编写JPQL语句,并通过类似“:name”来映射@Param指定的参数,就像例子中的第三个findUser函数一样。

Spring-data-jpa 的能力远不止本文提到的这些,由于本文主要以整合介绍为主,对于Spring-data-jpa的使用只是介绍了常见的使用方式。诸如@Modifying操作、分页排序、原生SQL支持以及与Spring MVC的结合使用等等内容就不在本文中详细展开,这里先挖个坑,后续再补文章填坑,如您对这些感兴趣可以关注我博客或简书,同样欢迎大家留言交流想法。

 

5、Controller层

在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,而描述主要来源于函数等命名产生,对用户并不友好,我们通常需要自己增加一些说明来丰富文档内容。如下所示,我们通过@ApiOperation注解来给API增加说明、通过@ApiImplicitParams@ApiImplicitParam注解来给参数增加说明。

package com.linjb.controller;

 

import java.util.List;

 

import org.springframework.beans.factory.annotation.Autowired;

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.RestController;

import com.linjb.model.PoliticalStatus;

import com.linjb.model.PoliticalStatusRepository;

import io.swagger.annotations.ApiImplicitParam;

import io.swagger.annotations.ApiOperation;

 

@RestController

@RequestMapping(value="/politicalStatus")

public class Controller {

 

@Autowired

private PoliticalStatusRepository politicalStatusRepository;

@ApiOperation(value="获取政治面貌列表", notes="查询所有")

@RequestMapping(value={"/findAll"},method=RequestMethod.POST)

public List<PoliticalStatus> findAll(){

return politicalStatusRepository.findAll();

}

@ApiOperation(value="创建政治面貌", notes="根据 PoliticalStatus 对象创建政治面貌")

@ApiImplicitParam(name = "politicalStatus", value = "政治面貌对象", required = true, dataType = "PoliticalStatus")

@RequestMapping(value="/save",method=RequestMethod.POST)

public String save(@RequestBody PoliticalStatus politicalStatus){

if(politicalStatus==null){

return "politicalStatus==null";

}

System.out.println(politicalStatus);

politicalStatusRepository.save(politicalStatus);

return "success";

}

@ApiOperation(value="根据名称获取政治面貌列表", notes="全名查询")

@RequestMapping(value="/findByPoliticalStatusName",method=RequestMethod.POST)

public PoliticalStatus findByPoliticalStatusName(@RequestBody String politicalStatusName){

System.out.println("politicalStatusName="+politicalStatusName);

return politicalStatusRepository.findByPoliticalStatusName(politicalStatusName);

}

@ApiOperation(value="根据名称获取政治面貌列表", notes="模糊查询")

@RequestMapping(value="/fuzzyQueryByPoliticalStatusName",method=RequestMethod.POST)

public List<PoliticalStatus> fuzzyQueryByPoliticalStatusName(@RequestBody String politicalStatusName){

System.out.println("politicalStatusName="+politicalStatusName);

return politicalStatusRepository.fuzzyQueryByPoliticalStatusName(politicalStatusName);

}

@ApiOperation(value="根据Id获取政治面貌", notes="Id查询")

@RequestMapping(value="/findByPoliticalStatusId",method=RequestMethod.POST)

public PoliticalStatus findByPoliticalStatusId(@RequestBody Integer politicalStatusId){

System.out.println("politicalStatusId="+politicalStatusId);

return politicalStatusRepository.findByPoliticalStatusId(politicalStatusId);

}

}

 

6、Application启动类

package com.linjb;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.builder.SpringApplicationBuilder;

import org.springframework.boot.context.web.SpringBootServletInitializer;

 

/**

* Spring Boot应用启动类

* @Copyright Copyright (C) 2019 linjb

* @author linjb

* @version 1.0

* @CreateDate 2019年1月31日下午10:25:16

*/

@SpringBootApplication

public class Application /*extends SpringBootServletInitializer*/{

 

public static void main(String[] args) {

SpringApplication.run(Application.class,args);

}

// @Override

// protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {

//

// return builder.sources(Application.class);

// }

}

 

7、创建Swagger2配置类

package com.linjb;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

 

import springfox.documentation.builders.ApiInfoBuilder;

import springfox.documentation.builders.PathSelectors;

import springfox.documentation.builders.RequestHandlerSelectors;

import springfox.documentation.service.ApiInfo;

import springfox.documentation.spi.DocumentationType;

import springfox.documentation.spring.web.plugins.Docket;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

 

@Configuration

@EnableSwagger2

public class Swagger2 {

 

@Bean

public Docket createRestApi() {

return new Docket(DocumentationType.SWAGGER_2)

.apiInfo(apiInfo())

.select()

.apis(RequestHandlerSelectors.basePackage("com.linjb"))

.paths(PathSelectors.any())

.build();

}

 

private ApiInfo apiInfo() {

return new ApiInfoBuilder()

.title("Spring Boot 使用 Spring-data-jpa 简化数据访问层")

.description("政治面貌 API 操作")

.termsOfServiceUrl("https://blog.csdn.net/qq_26629277")

.contact("程序员linjb")

.version("1.0")

.build();

}

 

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值