[由零开始] 了解和使用 Spring Data JPA 框架

Spring Data JPA 框架

简介

  • Spring Data Jpa 是应⽤于Dao层的⼀个框架,简化数据库开发的,作⽤和Mybatis框架⼀样,但是在使
    ⽤⽅式和底层机制是有所不同的。最明显的⼀个特点,Spring Data Jpa 开发Dao的时候,很多场景我们
    连sql语句都不需要开发。由Spring出品。

  • Spring Data JPA 是 Spring 基于JPA 规范的基础上封装的⼀套 JPA 应⽤框架,可使开发者⽤极简的
    代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常⽤功能!学习并使⽤
    Spring Data JPA 可以极⼤提⾼开发效率。

  • 说明:Spring Data JPA 极⼤简化了数据访问层代码。
    如何简化呢?使⽤了Spring Data JPA,我们Dao层中只需要写接⼝,不需要写实现类,就⾃动具有
    了增删改查、分⻚查询等⽅法。
    使⽤Spring Data JPA 很多场景下不需要我们⾃⼰写sql语句

JPA规范和Hibernate之间的关系

Spring Data JPA 是 Spring 提供的⼀个封装了JPA 操作的框架,⽽ JPA 仅仅是规范,单独使⽤规范⽆法
具体做什么,那么Spring Data JPA 、 JPA规范 以及 Hibernate (JPA 规范的⼀种实现)之间的关系是什
么?

[由零开始] 了解和使用 Spring Data JPA 框架_第1张图片

JPA 是⼀套规范,内部是由接⼝和抽象类组成的,Hiberanate 是⼀套成熟的 ORM 框架,⽽且
Hiberanate 实现了 JPA 规范,所以可以称 Hiberanate 为 JPA 的⼀种实现⽅式,我们使⽤ JPA 的 API 编
程,意味着站在更⾼的⻆度去看待问题(⾯向接⼝编程)。
Spring Data JPA 是 Spring 提供的⼀套对 JPA 操作更加⾼级的封装,是在 JPA 规范下的专⻔⽤来进⾏数
据持久化的解决⽅案。

Spring Data JPA 常用注解

1.@Entity:标识实体类是JPA实体,告诉JPA在程序运行时生成实体类对应表

2.@Table:设置实体类在数据库所对应的表名

3.@Id:标识类里所在变量为主键

4.@GeneratedValue:设置主键生成策略,此方式依赖于具体的数据库

5.@Column:表示属性所对应字段名进行个性化设置

6.@Transient:表示属性并非数据库表字段的映射,ORM框架将忽略该属性

7.@Temporal:(很重要)

当我们使用到java.util包中的时间日期类型,则需要此注释来说明转化成java.util包中的类型。

注入数据库的类型有三种:

TemporalType.DATE(2008-08-08)

TemporalType.TIME(20:00:00)

TemporalType.TIMESTAMP(2008-08-08 20:00:00.000000001)

8.@Enumerated:(很重要)

使用此注解映射枚举字段,以String类型存入数据库

注入数据库的类型有两种:EnumType.ORDINAL(Interger)、EnumType.STRING(String)

9.@Embedded@Embeddable

当一个实体类要在多个不同的实体类中进行使用,而其不需要生成数据库表

@Embeddable:注解在类上,表示此类是可以被其他类嵌套

@Embedded:注解在属性上,表示嵌套被@Embeddable注解的同类型类

10.@ElementCollection:集合映射

11.@CreatedDate@CreatedBy@LastModifiedDate@LastModifiedBy:(很重要)

表示字段为创建时间字段(insert自动设置)、创建用户字段(insert自动设置)、最后修改时间字段(update自定设置)、最后修改用户字段(update自定设置)

用法:

1、@EntityListeners(AuditingEntityListener.class):申明实体类并加注解

​ 2 、实现AuditorAware类

3、springboot 启动类加上注解@EnableJpaAuditing

4、在实体类中属性中加上面四种注解

后续会写个这个的demo

12.@MappedSuperclass:(很重要)

实现将实体类的多个属性分别封装到不同的非实体类中

注解的类将不是完整的实体类,不会映射到数据库表,但其属性将映射到子类的数据库字段
  注解的类不能再标注@Entity或@Table注解,也无需实现序列化接口

注解的类继承另一个实体类 或 标注@MappedSuperclass类,他可使用@AttributeOverride 或 @AttributeOverrides注解重定义其父类属性映射到数据库表中字段。

具体使用:https://www.w3cschool.cn/java/jpa-entitymanager.html

Spring Data JPA 使用

  • 导入坐标

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.3.RELEASEversion>
        <relativePath/> 
    parent>
    <groupId>com.examplegroupId>
    <artifactId>demoartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>demoname>
    <description>Demo project for Spring Bootdescription>

    <properties>
        <java.version>1.8java.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-jpaartifactId>
        dependency>
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.21version>
        dependency>
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.10version>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-annotationsartifactId>
            <version>2.9.7version>
        dependency>
    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

project>

  • 配置 Spring 的配置⽂件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true
    username: root
    password: root
    # 使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    filters: stat
    initialSize: 1
    minIdle: 3
    maxActive: 20
    # 配置获取连接等待超时的时间showBussMonthRentReport
    maxWait: 10000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 10000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 30000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    # 打开PSCache,并且指定每个连接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20   # 指定每个连接上PSCache的大小
    jpa:
      hibernate:
        ddl-auto: update  # 第一次建表create  后面用update,要不然每次重启都会新建表
        show-sql: true #打印执行的sql语句
      database-platform: org.hibernate.dialect.MySQL5InnoDBDialect #设置数据库方言  记住必须要使用 MySQL5InnoDBDialect 指定数据库类型对应InnoDB  ;如果使用MySQLDialect 则对应的是MyISAM

  • 编写实体类,使⽤ JPA 注解配置映射关系
package com.example.demo.model;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;



@Setter
@Getter
@ToString
@Entity
@Table(name = "hot")
public class Hot  {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "requirements")
    private String requirements;

    @Column(name = "salary")
    private String salary;

    @Column(name = "company_name")
    private String companyName;

    @Column(name = "company_label")
    private String companyLabel;

    @Column(name = "company_logo")
    private String companyLogo;

    @Transient
    private String company;


}

  • 编写 接⼝
package com.example.demo.dao;

import com.example.demo.model.Hot;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

/**
* ⼀个符合SpringDataJpa要求的Dao层接⼝是需要继承JpaRepository和
JpaSpecificationExecutor
*
* JpaRepository<操作的实体类类型,主键类型>
* 封装了基本的CRUD操作
*
* JpaSpecificationExecutor<操作的实体类类型>
* 封装了复杂的查询(分⻚、排序等)
*
*/
public interface HotDao  extends JpaRepository<Hot,Long>, JpaSpecificationExecutor<Hot> {
    
    @Query("from Resume where id=?1 and name=?2")
	public List<Hot> findByJpql(Long id,String name);
    
    
    /**
    * 使⽤原⽣sql语句查询,需要将nativeQuery属性设置为true,默认为false(jpql)
    * @param name
    * @param companyName
    * @return
    */
    @Query(value = "select * from tb_resume where name like ?1 and
					company_name like ?2",nativeQuery = true)
    public List<Hot> findBySql(String name,String companyName);
           
    /**
    * ⽅法命名规则查询
    * 按照name模糊查询(like)
    * ⽅法名以findBy开头
    * -属性名(⾸字⺟⼤写)
    * -查询⽅式(模糊查询、等价查询),如果不写查询⽅式,默认等价
    查询
    */       
     public List<Hot> findByNameLikeAndCompanyName(String name,String
companyName);      
    
    
    
}

  • 测试
@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests {

    @Autowired
    private HotDao hotDao;

    @Test
    void contextLoads() {
        Hot hot= new Hot();
        hot.setCompanyName("peng");
        hotDao.saveAndFlush(hot);
    }

}

分析

 /**
     * ========================针对查询的使⽤进⾏分析=======================
     * ⽅式⼀:调⽤继承的接⼝中的⽅法 findOne(),findById()
     * ⽅式⼆:可以引⼊jpql(jpa查询语⾔)语句进⾏查询 (=====>>>> jpql 语句类似于
     sql,只不过sql操作的是数据表和字段,jpql操作的是对象和属性,⽐如 from Resume where
     id=xx) hql
     * ⽅式三:可以引⼊原⽣的sql语句
     * 规则查询,也就是说定义的接⼝⽅法名是按照⼀定规则形成的,那么框架就能够理解我们的意图
     * * ⽅式五:动态查询
     * * service层传⼊dao层的条件不确定,把service拿到条件封装成⼀个对象传递给
     * Dao层,这个对象就叫做Specification(对条件的⼀个封装)
     * *
     * *
     * * // 根据条件查询单个对象
     * * Optional findOne(@Nullable Specification var1);
     * * // 根据条件查询所有
     * * List findAll(@Nullable Specification var1);
     * * // 根据条件查询并进⾏分⻚
     * * Page findAll(@Nullable Specification var1, Pageable
     * var2);
     * * // 根据条件查询并进⾏排序
     * * List findAll(@Nullable Specification var1, Sort
     * var2);
     * * // 根据条件统计
     * * long count(@Nullable Specification var1);
     * *
     * * interface Specification
     * * toPredicate(Root var1, CriteriaQuery var2,
     * CriteriaBuilder var3);⽤来封装查询条件的
     * * Root:根属性(查询所需要的任何属性都可以从根对象中获取)
     * * CriteriaQuery ⾃定义查询⽅式 ⽤不上
     * * CriteriaBuilder 查询构造器,封装了很多的查询条件(like =
     * 等)
     * *
     * *
     * */

你可能感兴趣的:(Spring,Mybatis)