首先简单介绍一下SpringData:Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。


    现在我们可以来聊一聊Spring Data JPA。从Spring Data的介绍以及JPA的介绍不难看出,Spring Data JPA是使用JPA标准的持久层工具。持久层工具,那就有意思了,我们已经有Hibernate和Mybatis等等好用的持久层工具了,为什么要用Spring Data JPA呢?这是一个好问题,我卖个关子,我们先来看看Spring Data如何与Spring进行整合。

1. Spring整合Spring Data JPA

        1.1 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>6.0.6</version>
</dependency>

        1.2 配置属性

#通用数据源配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot_jpa?charset=utf8mb4&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
# Hikari 数据源专用配置
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
# JPA 相关配置
#在 SrpingBoot 2.0 版本中,Hibernate 创建数据表的时候,默认的数据库存储引擎选择的是 MyISAM (之前好像是 InnoDB,这点比较诡异)。这个参数是在建表的时候,将默认的存储引擎切换为 InnoDB 用的。
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#配置在日志中打印出执行的 SQL 语句信息。
spring.jpa.show-sql=true
#配置指明在程序启动的时候要删除并且创建实体类对应的表。这个参数很危险,因为他会把对应的表删除掉然后重建。所以千万不要在生成环境中使用。只有在测试环境中,一开始初始化数据库结构的时候才能使用一次。
spring.jpa.hibernate.ddl-auto=update

    对spring.jpa.hibernate.ddl-auto属性感兴趣的同学,可以去下面这篇博客看看。

    1.3 创建实体类

import lombok.Data;

import javax.persistence.*;

/*
 * @Description TODO
 * @author Raindrop
 * @date 2019/8/22 9:10
 */
@Data       //lombok构建Get和Set方法
@Entity     //声明该类为实体类
@Table(name = "SpringDataJpa")      //该实体类对应的表名
public class Test {
    @Id     //该属性为主键
    @GeneratedValue(strategy =  GenerationType.IDENTITY)        //JPA通用策略生成器
    @Column(name = "id")        //数据表中列名
    private Integer id;

    @Column(name = "username", columnDefinition = "varchar(50) not null")   //数据表中列名以及列类型
    private String username;

    @Column(name = "email", columnDefinition = "varchar(50) not null")   //数据表中列名以及列类型
    private String email;

    @Column(name = "sex", columnDefinition = "varchar(50) not null")   //数据表中列名以及列类型
    private String sex;

    @Column(name = "age", columnDefinition = "varchar(50) not null")   //数据表中列名以及列类型
    private String age;
}

    1.4 创建dao层

          好了,我们的准备工作都已经做完了,接下来我们就可以快乐的进行CRUD了。

          创建Repository类

package run.halo.app.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import run.halo.app.model.entity.*;

import java.util.List;

public interface RaindropUserRepository extends JpaRepository<RaindropUser, Integer> {
    //自定义方法 根据方法名来创建sql语句
    //形成的SQL语句:select * from spring_data_jpa where userName = ?1
    RaindropUser findByUsername(String userName);

    //自定义方法 根据方法名来创建sql语句
    //形成的SQL语句:select * from spring_data_jpa where sex = ?1 and email=?2
    RaindropUser findBySexAndEmail(String sex, String email);

    //切记切记,native的使用方法   JPA使用nativeQuery=true来区分是不是原生SQL
    //以下方法是错误的,不可以使用原生的sql,而要是用对应的实体类以及属性来表示列和表名
    //@Query("select id,username from spring_data_jpa where age < :age")
    @Query("select new run.halo.app.model.entity.RaindropUser(raindrop.id," +
            "raindrop.username,raindrop.email,raindrop.sex," +
            "raindrop.age) from RaindropUser raindrop where raindrop.age < ?1")
    List<RaindropUser> findByLtAge(Integer age);
//    该示例也是错的
//    @Query("select new run.halo.app.model.entity.RaindropUser(a.id,a.username,a.email,a.sex,a.age) from spring_data_jpa a where age > ?1")
//    RaindropUser findByRtAge(Integer age);
}

    1.5 测试类

        

@Test
    public void Test(){
        RaindropUser raindropUser = new RaindropUser();
//        raindropUser.setEmail("123123@gmail.com");
//        raindropUser.setAge(12);
//        raindropUser.setUsername("Raindrop");
//        raindropUser.setSex("man");
//        继承自JpaRepository类都有一些基础方法,稍后讲解。该方法为保存数据
//        raindropUserRepository.save(raindropUser);
        List<RaindropUser> list = raindropUserRepository.findByLtAge(15);

        System.out.println("List: " + list.get(0));
//        RaindropUser raindropUser1 = raindropUserRepository.findByRtAge(10);
//        System.out.println(raindropUser);
//        System.out.println(raindropUser1);
    }

    1.6 JAP方法解析

        我们在Repository类中定义了findByUsername以及findBySexAndEmail方法,SpringData会根据方法名自动生成SQL语句来执行。

重点词汇以及生成的SQL语句

Keyword

Sample

JPQL snippet

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

Is,Equals

findByFirstnameIs,findByFirstnameEquals

… where x.firstname = ?1

Between

findByStartDateBetween

… where x.startDate between ?1 and ?2

LessThan

findByAgeLessThan

… where x.age < ?1

LessThanEqual

findByAgeLessThanEqual

… where x.age ⇐ ?1

GreaterThan

findByAgeGreaterThan

… where x.age > ?1

GreaterThanEqual

findByAgeGreaterThanEqual

… where x.age >= ?1

After

findByStartDateAfter

… where x.startDate > ?1

Before

findByStartDateBefore

… where x.startDate < ?1

IsNull

findByAgeIsNull

… where x.age is null

IsNotNull,NotNull

findByAge(Is)NotNull

… where x.age not null

Like

findByFirstnameLike

… where x.firstname like ?1

NotLike

findByFirstnameNotLike

… where x.firstname not like ?1

StartingWith

findByFirstnameStartingWith

… where x.firstname like ?1 (parameter bound with appended %)

EndingWith

findByFirstnameEndingWith

… where x.firstname like ?1 (parameter bound with prepended %)

Containing

findByFirstnameContaining

… where x.firstname like ?1 (parameter bound wrapped in %)

OrderBy

findByAgeOrderByLastnameDesc

… where x.age = ?1 order by x.lastname desc

Not

findByLastnameNot

… where x.lastname <> ?1

In

findByAgeIn(Collection ages)

… where x.age in ?1

NotIn

findByAgeNotIn(Collectionage)

… where x.age not in ?1

TRUE

findByActiveTrue()

… where x.active = true

FALSE

findByActiveFalse()

… where x.active = false

IgnoreCase

findByFirstnameIgnoreCase

… where UPPER(x.firstame) = UPPER(?1)