车车的Springboot学习日记(三)——jpa使用

73 阅读4分钟

JPA介绍

JPA(Java Persistence API)和JDBC类似,也是官方定义的一组接口,但是它相比传统的JDBC,它是为了实现ORM而生的,即Object-Relationl Mapping,它的作用是在关系型数据库和对象之间形成一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。

在之前,我们使用JDBC或是Mybatis来操作数据,通过直接编写对应的SQL语句来实现数据访问,但是我们发现实际上我们在Java中大部分操作数据库的情况都是读取数据并封装为一个实体类,因此,为什么不直接将实体类直接对应到一个数据库表呢?也就是说,一张表里面有什么属性,那么我们的对象就有什么属性,所有属性跟数据库里面的字段一一对应,而读取数据时,只需要读取一行的数据并封装为我们定义好的实体类既可以,而具体的SQL语句执行,完全可以交给框架根据我们定义的映射关系去生成,不再由我们去编写,因为这些SQL实际上都是千篇一律的。

配置文件编写

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    password: 123456
    url: jdbc:mysql://localhost:3306/jpa
    username: root
  jpa:
    #开启SQL语句执行日志信息 
    show-sql: true 
    hibernate: 
    #配置为自动创建 
        ddl-auto: create

声明连接的是MySQL数据库。

导入依赖

org.springframework.boot spring-boot-starter-data-jpa

实体注解

@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
@Entity
@Table(name = "orm_user")
@ToString(callSuper = true)
public class User extends AbstractAuditModel {
    /**
     * 用户名
     */
    private String name;

    /**
     * 加密后的密码
     */
    private String password;

    /**
     * 加密使用的盐
     */
    private String salt;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 手机号码
     */
    @Column(name = "phone_number")
    private String phoneNumber;

    /**
     * 状态,-1:逻辑删除,0:禁用,1:启用
     */
    private Integer status;

    /**
     * 上次登录时间
     */
    @Column(name = "last_login_time")
    private Date lastLoginTime;

    /**
     * 关联部门表
     * 1、关系维护端,负责多对多关系的绑定和解除
     * 2、@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(User)
     * 3、inverseJoinColumns指定外键的名字,要关联的关系被维护端(Department)
     * 4、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
     * 即表名为user_department
     * 关联到主表的外键名:主表名+下划线+主表中的主键列名,即user_id,这里使用referencedColumnName指定
     * 关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,department_id
     * 主表就是关系维护端对应的表,从表就是关系被维护端对应的表
     */
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "orm_user_dept", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "dept_id", referencedColumnName = "id"))
    private Collection<Department> departmentList;

}

实体注解

  • @EqualsAndHashCode(callSuper = true):生成equalshashCode方法时调用父类的同名方法。
  • @NoArgsConstructor:生成一个无参的构造方法。
  • @AllArgsConstructor:生成一个包含所有参数的构造方法。
  • @Data:自动生成gettersettertoString等方法。
  • @Builder:生成一个内部静态类Builder,用于链式调用设置对象属性。
  • @Entity:声明这是一个实体类。
  • @Table(name = "orm_user"):指定该实体类对应的数据库表的名称为"orm_user"。
  • @ToString(callSuper = true):生成toString方法时包含父类的属性。

DAO层编写

需要自定义接口继承JpaRepository

@Repository
public interface UserDao extends JpaRepository<User, Long> {

}

注意JpaRepository有两个泛型,前者是具体操作的对象实体,也就是对应的表,后者是ID的类型。 接下来我们仅需在SpringbootTest中进行JPA功能测试。只需要将UserDao对象进行创建,就可以进行crud操作了。

crud操作

@Test
public void testSave() {
    String salt = IdUtil.fastSimpleUUID();
    User testSave3 = User.builder().name("testSave3").password(SecureUtil.md5("123456" + salt)).salt(salt).email("testSave3@xkcoding.com").phoneNumber("17300000003").status(1).lastLoginTime(new DateTime()).build();
    userDao.save(testSave3);

    Assert.assertNotNull(testSave3.getId());
    Optional<User> byId = userDao.findById(testSave3.getId());
    Assert.assertTrue(byId.isPresent());
    log.debug("【byId】= {}", byId.get());
}
@Test
public void testDelete() {
    long count = userDao.count();
    userDao.deleteById(1L);
    long left = userDao.count();
    Assert.assertEquals(count - 1, left);
}

/**
 * 测试修改
 */
@Test
public void testUpdate() {
    userDao.findById(1L).ifPresent(user -> {
        user.setName("JPA修改名字");
        userDao.save(user);
    });
    Assert.assertEquals("JPA修改名字", userDao.findById(1L).get().getName());
}

/**
 * 测试查询单个
 */
@Test
public void testQueryOne() {
    Optional<User> byId = userDao.findById(1L);
    Assert.assertTrue(byId.isPresent());
    log.debug("【byId】= {}", byId.get());
}

/**
 * 测试查询所有
 */
@Test
public void testQueryAll() {
    List<User> users = userDao.findAll();
    Assert.assertNotEquals(0, users.size());
    log.debug("【users】= {}", users);
}
  • 测试增加,利用userDao.save()方法,将User进行存储进数据库中。
  • 测试删除,利用userDao.deleteById(),根据主键id进行删除。
  • 测试查找,利用userDao.findById()和userDao.findAll()进行查找。