SpringBoot中JPA的使用

375 阅读5分钟
JPA、Hibernate和Spring Data JPA关系

image.png

JPA

JPA全称是Java Persistence API,即java持久化API,是sun公司推出的一套基于ORM的规范,内部由一系列的接口和抽象类构成。JPA仅仅是一种规范

Hibernate

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。Hibernate实现了JPA规范

spring data jpa

spirng data jpa是spring提供的一套简化JPA开发的框架,按照约定好的【方法命名规则】写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作。同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查询等等。Spring Data JPA是对JPA进行更高级的封装

总结

在SpringData中,提供了一套统一的接口来实现对数据访问层的操作,就是Repository接口。在接口中提供了基本的CRUD,查询,排序和分页的相关操作。

SpringData Jpa的默认实现就是Hibernate。简单来说就是:SpringData Jpa 实现了 SpringData,Hibernate 又实现了 SpringData Jpa。所以最终干活的实际上是 Hibernate。

SpringBoot中Jpa的基本使用
1.创建项目 导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
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

# JPA 相关配置
# 将默认的存储引擎切换为 InnoDB
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
# 控制是否打印运行时的SQL语句与参数信息
spring.jpa.show-sql=true
# 控制是否可以基于程序中Entity的定义自动创建或者修改DB中表结构
spring.jpa.hibernate.ddl-auto=update
3.建立数据实体类
@Data  //lombok 注解  生成get set 等
@Entity //告诉JPA这是一个实体类(一个和数据表映射的类)
@Table(name = "t_user") //配置当前实体类和哪张表对应;可以省略不写,如果省略默认表名和实体的名称保持一致。
@EntityListeners(value = AuditingEntityListener.class) //开启自动审计
public class UserEntity {
    @Id //代表这是主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) //主键生成规则 IDENTITY 自增
    private Long id;
    @Column(length = 32) //声明了字符字段的长度。如果不这么声明,则系统会采用 255 作为该字段的长度
    private String name;
    private String password;

    @CreatedDate
    private Date createTime;
    @LastModifiedDate
    private Date updateTime;
}

基本常用注解使用见上面的注释,其他注解可以用到再查询

4.实现一个持久类

在 Spring Data JPA 的世界里,实现一个持久层的服务是一个非常简单的事情。以上面的 UserDO 实体对象为例,我们要实现一个增加、删除、修改、查询功能的持久层服务,那么我只需要声明一个接口,这个接口继承org.springframework.data.repository.Repository 接口或者他的子接口就行,其中 T 是数据库实体类,ID 是数据库实体类的主键。 然后再简单的在这个接口上增加一个 @Repository 注解就结束了。

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

一行代码也不用写。那么针对 UserDO 这个实体类,我们已经拥有常规的增删改查的功能

userRepository.findAll();
userRepository.findOne(1l);
userRepository.save(user);
userRepository.delete(user);
userRepository.count();
userRepository.exists(1l);
5.启动类增加自动审计注解,实现自动填充功能(可选)
@EnableJpaAuditing //利用jpa可以给MySQL列属性自动赋值,例如一些创建时间,修改时间
@SpringBootApplication
public class AuthorityCenterApplication {
    public static void main(String[] args) {
        SpringApplication.run(AuthorityCenterApplication.class, args);
    }
}
6.单元测试

第一个是插入,第二个是查询,执行完第一个可以到数据库刷新下看是否有数据插入

@SpringBootTest
class SpringJpaApplicationTests {

    @Autowired
    private UserRepository userRepository;

    @Test
    void contextLoads() {

    }

    /**
     * 新增操作
     */
    @Test
    void testSave() {
        UserEntity user = new UserEntity();
        user.setName("王五");
        user.setPassword("123456");
        userRepository.save(user);
    }

    /**
     * 更新操作
     */
    @Test
    void testUpdate() {
        Optional<UserEntity> optional=userRepository.findById(1L);
        if (optional.isPresent()){
            UserEntity user =  optional.get();
            user.setName("李四");
            userRepository.save(user);
        }
    }

    /**
     * 删除操作
     */
    @Test
    void testDelete() {
        UserEntity user = new UserEntity();
        user.setId(1L);
        userRepository.delete(user);
    }

    /**
     * 获取所有用户列表
     */
    @Test
    void testFindAll() {
        List<UserEntity> userEntities = userRepository.findAll();
        System.out.println(userEntities);
    }
}
扩展查询

当你继承JpaRepository后,自带的查询方法无法满足的时候,jpa还为我们提供了下面几种查询方式

根据属性查询
//自定义简单查询 主要的语法是findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy后面跟属性名称:
List<UserEntity> findByName(String name);

//也使用一些加一些关键字And 、 Or
UserEntity findByNameOrPassword(String name, String age);

//修改、删除、统计也是类似语法
void deleteById(Long id);
Long countByName(String userName);

//基本上 SQL 体系中的关键词都可以使用,例如: LIKE 、 IgnoreCase、 OrderBy。
List<UserEntity> findByNameLike(String email);
UserEntity findByNameIgnoreCase(String userName);
List<UserEntity> findByNameOrderByNameDesc(String name);
自定义查询
@Query(nativeQuery = true, value = "SELECT * FROM t_user WHERE name = :name1 OR name = :name2 ") List<UserDO> findSQL(@Param("name1") String name1, @Param("name2") String name2);
分页查询

分页需要设置分页参数类Pageable,初始化主要是有两个参数:第一个是查询的页码(下标从0开始),第二个是每页查询的条数

查询方式如下

@Test
public void testPageQuery() throws Exception {
    //设置分页参数
    Pageable pageable = PageRequest.of(0,1);
    System.out.println(userRepository.findAll(pageable).getContent());
}

Page接口是封装为Spring Data Jpa 内部的page bean,它的常用方法如下:

//获取总页数
int getTotalPages();
//获取总记录数    
long getTotalElements();
//获取列表数据
List<T> getContent();
总结

可以看到,我们所做的全部事情仅仅是在 SpingBoot 工程里面增加数据库配置信息,声明一个 UserDO 的数据库实体对象,然后声明了一个持久层的接口,改接口继承自 org.springframework.data.jpa.repository.JpaRepository 接口。然后,系统就自动拥有了丰富的增加、删除、修改、查询功能。查询功能甚至还拥有了排序和分页的功能。

完整项目地址:

github.com/cocoamu/spr…