Spring Data JPA 入门

1. 什么是Spring Data JPA

JPA 全称 Java Persistence Api, 中文是java 持久化API。
它是当今世界上最流行的ORM (Object-Relational Mapping)框架。

当年我们都感觉传统的ORM框架hibernate 相当的难用和臃肿,特别多联表查询, 然后选择更轻量级和更直观的的Mybatise. 但其实Mybaise 并不是1个ORM框架, 它是拥抱sql的。 对熟悉sql的开发人员更加友好。

当微服务大行其道时, 业务细分下, 通常我们不会在服务中对数据库进行复制的sql查询。 这时mybasise 的优势就不大了, 很多开发人员返回了JPA 的怀抱, 代码更加面向对象是一 回事, 而且JPA也支持用SQL查询。

JPA并不是1个ORM的具体实现, JPA只是定义了1个ORM的规范, 里面只提供了接口, 所以JPA必须配合Hiberate 或者其他ORM框架来使用, 但是hibernate是最常见的。



2. JPA 相对于 Mybatise 的其他优势.

Mybatise 毕竟是拥抱sql的, 决定了Mybasie 只适用于操作关系型数据库, 例如mysql , oracle, pgsql等…
而JPA可以用相同的接口规范, 用于NOSQL 数据库, 例如Redis,mongo, ES, NEO4j等… 所以JPA是更加有前景的。

在高并发环境下, 一个项目很可能不会只使用单1关系数据库, 很可能我们会用Kafka, redis 等缓存技术, 用ES进行模糊查询, 这时能统一接口规范的JPA就大有发挥空间了。

还有哦, JpaRepostory 接口默认已经帮你写好了很多方法, 例如findById findAll等, 不像mybatise要写很多这种查询接口的…



3. JPA 与 JDBC的 关系

  1. 都与数据库操作有关, JPA 是JDBC 的升华, 升级版, JDBC只适用于关系型数据库
  2. JDBC和JPA都是一组规范接口, 并不提供提供实现。

不同处:
4. JDBC 需要 各个关系型数据库实现(各种数据库driver), JPA需要ORM框架实现(Hibernate)
5. JDBC 使用sql语句与数据库通讯, JPA用面向对象方式, 生成sql后利用JBDC与数据库通讯
6. 所以JPA依赖于JDBC

JPA
ORM
JDBC
database driver
Dataabse

下面会用1个user service 的例子, 将user service的持久化由 mybatise 改成 JPA + hibernate。



4. 引入依赖

在pom.xml 中, 我们去掉mybatise 的依赖。
并引入

   		<dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-jpaartifactId>
        dependency>

注意我们使用的是spring-boot-starter-data-jpa, 这个sub pom.xml 已经包含spring-data-jpa 和Hibernate
所以我们不需要另外引入Hibernate 依赖了。

如果我们引入的不是spring-boot-starter-data-jpa, 而是spring-data-jpa, 则还需要引入ORM.
当然mysql的驱动还是需要的

   		<dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
        dependency>

5. 配置数据库和JPA信息.

对于原来的yml数据库, 原来的格式可以通用
但是我们要引入一些jpa的配置

spring:
  datasource:
    url: jdbc:mysql://43.138.222.61:3306/demo_cloud_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
    username: cloud_user
    password: '{cipher}323e2265acd321eaec76a88bfa710f5f3673c58f8e6e1bbe2944f08b9518ac0c'
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maxLifeTime: 30000
  jpa:
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect

下面是一些jpa配置解释

spring.jpa.generate-ddl

这个配置在开发中可以设置为true, 默认是false, 一旦开启, 则enable了正行工程, 这个是配置自动生成数据库表的前提
一些概念
逆向工程: 根据已存在数据库生成所对应的pojo类
正向工程: 根据已存在的pojo类生成对应的数据库表

spring.jpa.hibernate.ddl-auto

create 代表每次运行程序时, 都会把原来的表删除, 然后重新创建表, 慎用
create-drop: 每次运行数据库,都会创建数据表, 使用完后将表删除,慎用
none: 不生效
update: 如果我们的表结构和实体类没有一一映射,或者实体类发生改变, 那么会对数据表更新表结构.
假如数据库表不存在, 则会创建1个表, 在开发中经常使用
validate: 如果实体类和数据表映射不一致, 会抛出异常, 在测试环境经常使用

spring.jpa.properties.hibernate.dialect

采用什么数据库方言

其实类比我们生活中的方言,方言就是某个地方的特色语言,这个语言区别于其他地方的语言,比如在江苏,有南通方言、盐城方言、苏州方言,只要你是当地人,你基本能听懂当地的方言。

对于数据库的方言,也是同样的道理,MySQL是一种方言,Oracle也是一种方言,当然他们都遵循SQL规范的,就好比南通方言、盐城方言都遵循普通话规范,然后有各自的一个扩展性和特色。举个例子,MySQL分页是用limit关键字,而Oracle分页是用rownum关键字。



6.修改User实体类

import lombok.Data;
import javax.persistence.*;

@Entity // to be pojo class of Hibernate
@Data
@Table(name = "tb_user")
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {

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

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

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

}
@Entity注解

注意要引入javax.persistence包内的注解而不是Hibernate包的
表示这个是1个实体类

@Table

表示对应数据库的表名

@Id

表示这是1个主键

@GeneratedValue(strategy = GenerationType.IDENTITY)

设置id键生成策略
GenerationType.IDENTITY -> 表示自增列

@Column(name=“id”)

表示对应的表列名

7. 创建接口UserDao (继承 JpaRepository 接口)

你看, 借口内什么方法都不用写了

import cn.itcast.user.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;

/*
   * JpaRepository , JpaRepository provide some default crud methods,
   * T means the Entity Class,
   * ID means the data type of private key , or the attrible which has @Id

 */
public interface UserDao extends JpaRepository<User, Long> {

}

7. 编写测试用例for 读取 和 写入方法:

import cn.itcast.user.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;


@Slf4j
@DataJpaTest //default will auto rollback
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class UserDaoTest {

    @Autowired
    private UserDao userDao; //springboot will create an instance of the interface while starting

    @Test
    @DisplayName("test add User")
    public void testAddUser(){
        User user = new User();
        user.setUsername("Alice5");
        user.setAddress("The 5th School");
        userDao.save(user);
        log.info("User id: {}",user.getId());
        assertTrue(0 < user.getId(),"id should be generated");
    }

    @Test
    @DisplayName("find one User")
    public void findUserTest1(){
        Optional<User> optionaluser = userDao.findById(2L);
        User user = optionaluser.get();
        log.info(String.valueOf(user));
        assertNotNull(user);
    }


}

输出
在这里插入图片描述

你可能感兴趣的:(Java,JPA,数据库,java,开发语言)