Spring Boot整合Spring Data JPA学习笔记

2022年8月2日12:15:48

Spring Boot 整合Spring Data JPA

ORM思想

主要目的:操作实体类相当于操作数据库表

建立两个关系:

1.建立实体类和表的映射关系
2.建立实体类中的属性和表中字段的映射关系

不再重点关注sql语句(这是ORM思想我感觉最好的一个地方)

实现了ORM思想的框架:mybatis,hibernate

JPA底层实现数据库语言的还是hibernate

Spring Boot 整合Spring Data JPA 的时候Dao层的repository接口类继承的四个接口的详解

Spring Boot 整合Spring Data JPA 的时候需要定义Dao 层,就是repository类,这个类是一个接口,来继承一个接口,一共有四个接口

1.Repository接口

提供了方法名称命名查询方式
提供了基于@Query注解查询与更新

下面是repository类的代码

publicinterfacePersonRepositoryByNameextendsRepository<Person,Integer>{//一定注意下方法名:findBy(关键字)+属性名(首字母大写)
    List<Person>findByName(String name);//按照姓名查找
    List<Person>findByAddress(String address);//按照地址查找
    List<Person>findByNameOrAge(String name,Integer age);//按照姓名或者年龄查找
    List<Person>findByNameLike(String name);//按照姓名模糊查找
    List<Person>findByAddressLike(String address);//按照地址模糊查找}

下面是一个测试代码

@SpringBootTestclassSpringbootSpringdatajpaApplicationTests{@Autowired
    PersonRepository personRepository;@Autowired
    PersonRepositoryByName personRepositoryByName;@TestpublicvoidtestSave(){
        Person person=newPerson();
        person.setAge(24);
        person.setName("张三");
        person.setAddress("济南市槐荫区");this.personRepository.save(person);}@TestpublicvoidtestFindByName(){
        List<Person> list=this.personRepositoryByName.findByName("张三");for(Person persons: list){
            System.out.println(persons);}}@TestpublicvoidtestFindByAddress(){
        List<Person> list=this.personRepositoryByName.findByAddress("济南市历下区");for(Person persons: list){
            System.out.println(persons);}}@TestpublicvoidtestFindByNameOrAge(){
        List<Person> list=this.personRepositoryByName.findByNameOrAge("李四",21);for(Person persons: list){
            System.out.println(persons);}}@TestpublicvoidtestFindByNameLink(){
        List<Person> list=this.personRepositoryByName.findByNameLike("李%");for(Person persons: list){
            System.out.println(persons);}}@TestpublicvoidtestFindByAddressLink(){
        List<Person> list=this.personRepositoryByName.findByAddressLike("济南市%");for(Person persons: list){
            System.out.println(persons);}}}

基于@Query注解查询与更新

首先还是需要建立一个repository接口来继承Repository接口,然后写方法

代码

publicinterfacePersonRepositoryQueryAnnotationextendsRepository<Person,Integer>{//使用@Query注解结合sql语句来实现查找,**注意**:?的顺序和形参的顺序是一一对应的
    nativeQuery=true的意思是告诉hibernate这是一个标准的sql语句@Query(value="select * from tb_person where name=?",nativeQuery=true)
    List<Person>queryByName(String name);@Query(value="update tb_person set name=? where id=?",nativeQuery=true)@Modifying//这是更新的注解与@Query注解配合使用来更新voidupdateNameById(String name,Integer id);}

测试代码:

@TestpublicvoidtestQueryByName(){
    List<Person> list=this.personRepositoryQueryAnnotation.queryByName("张三");for(Person persons: list){
        System.out.println(persons);}}@Test@Transactional//手动设置一个事务,更新操作必须在事务中@Rollback(value=false)//取消自动回滚publicvoidtestUpdateNameById(){this.personRepositoryQueryAnnotation.updateNameById("张三三",3);}}

2.CrudRepository接口

注意:CrudRepository接口是继承的Repository接口的,主要功能就是增删改查,而且CrudRepository接口的使用和JpaRepository接口的使用非常类似

CrudRepository接口中的方法都有[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YIAb4NvH-1618480041802)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\image-20210413213804466.png)]

接口类的实现代码

publicinterfaceCrudRepositoryextendsorg.springframework.data.repository.CrudRepository<Person,Integer>{}

测试增删改查的代码

//插入数据@TestpublicvoidtestInsert(){
    Person person=newPerson();
    person.setName("张三丰");
    person.setAddress("青岛市");
    person.setAge(333);
    crudRepository.save(person);}//注意CrudRepository的save方法既可以插入又可以更新@TestpublicvoidtestInsert(){
    Person person=newPerson();//**注意**:如果你想要更新的话必须指定id,使用setId()方法
    person.setId(4);
    person.setName("张三丰");
    person.setAddress("青岛市黄岛区");
    person.setAge(333);
    crudRepository.save(person);}//按照Id进行指定删除@TestpublicvoidtestDeleteById(){
    crudRepository.deleteById(5);}//按照指定Id进行查找@TestpublicvoidtestFindById(){
    Optional<Person> persons= crudRepository.findById(4);
    System.out.println(persons);}//查找全部@TestpublicvoidtestFindAll(){
        Iterable<Person> all= crudRepository.findAll();
        System.out.println(all);}

3.PagingAndSortingRepository接口

这个类继承了CrudRepository接口,主要功能是排序查询和分页查询

首先我们看一下接口类的实现

publicinterfaceRepositoryPagingAndSortingextendsPagingAndSortingRepository<Person,Integer>{}

PagingAndSortingRepository接口中的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-geuBbPid-1618480041806)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\image-20210414165917747.png)]

测试代码

//排序查询@TestpublicvoidtestSort(){//Order来定义排序规则DESC是降序,ASC是升序
Order order=newOrder(Sort.Direction.DESC,"id");//spring boot2.0以上版本的Sort重写了,不能new Sort了,要用Sort.by
 Sort sort=Sort.by(order);
     List<Person> persons=(List<Person>) repositoryPagingAndSorting.findAll(sort);for(Person list: persons){
         System.out.println(list);}}//分页查询@TestpublicvoidtestPaging(){//spring boot2.0以上版本不能用Pageable了要使用PageRequest.of,返回PageRequest
PageRequest pageable=PageRequest.of(1,2);
     Page<Person> page= repositoryPagingAndSorting.findAll(pageable);
     System.out.println("总条数"+page.getTotalElements());
     System.out.println("总页数"+page.getTotalPages());
     List<Person> list= page.getContent();for(Person persons:list){
         System.out.println(persons);}}//分页排序查询(将上面两个方法结合)@TestpublicvoidtestPagingAndSort(){
    Order order=newOrder(Sort.Direction.DESC,"id");
    Sort sort=Sort.by(order);
    PageRequest pageable= PageRequest.of(0,2,sort);
     Page<Person> page= repositoryPagingAndSorting.findAll(pageable);
     System.out.println("总条数"+page.getTotalElements());
     System.out.println("总页数"+page.getTotalPages());
     List<Person> list= page.getContent();for(Person persons:list){
         System.out.println(persons);}}

4.JpaRepository接口

该类继承了PagingAndSortingRepository接口,可以对父接口中的方法返回值进行适配

接口类的定义

publicinterfacePersonRepositoryextendsJpaRepository<Person,Integer>{}

JpaRepository接口中的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZiSoi0D-1618480041807)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\image-20210414171553284.png)]

测试代码

//分页查询@TestpublicvoidtestJpaRepository(){
    Sort sort=Sort.by(Sort.Direction.DESC,"id");
    PageRequest pageable=PageRequest.of(0,2,sort);
    Page<Person> page= personRepository.findAll(pageable);
    List<Person> list= page.getContent();for(Person persons:list){
        System.out.println(persons);}}//按照顺序查询@TestpublicvoidtestJpaRepositoryFind(){
        Sort sort= Sort.by(Sort.Direction.DESC,"id");//注意这里的personRepository.findAll(sort)不需要进行强制类型转换,因为JpaRepository实现了对父接口的返回值类型的适配
        List<Person> list= personRepository.findAll(sort);for(Person persons: list){
            System.out.println(persons);}}

=5.JpaSpecificationExecutor接口==

JpaSpecificationExecutor没有继承前面的四个接口的任意一个,它是独立的一个,所以它有时候需要配合其他的接口使用。JpaSpecificationExecutor接口主要用于对一些复杂条件的查询

JpaSpecificationExecutor接口经常配合JpaSpecificationExecutor接口使用

下面是JpaSpecificationExecutor接口中的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xKYO59kz-1618480041809)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\image-20210414191340758.png)]

接口类的代码

publicinterfaceRepositoryJpaSeextendsJpaSpecificationExecutor<Person>/*只需要写实体类*/,JpaRepository<Person,Integer>{}

测试代码

//单条件查询@TestpublicvoidtestJpaSe(){
    Specification spe=newSpecification(){@Override/**root是我们实体类的一个封装类
  			*	criteriaQuery:封装了我们要执行的查询中的各个部分的信息
  			*	criteriaBuilder:定义不同的查询条件
  			*/public PredicatetoPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder){
            Predicate predicate= criteriaBuilder.equal(root.get("name"),"张三三");return predicate;}};
    Optional list= repositoryJpaSe.findOne(spe);
    System.out.println(list);}//多条件查询@TestpublicvoidtestJpaSpe(){
    Specification spe=newSpecification(){@Overridepublic PredicatetoPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder){//多条件查询的时候我们就将我们的多个查询条件放进Predicate类型的List中
            Predicate name= criteriaBuilder.equal(root.get("name"),"李四");
            Predicate age= criteriaBuilder.equal(root.get("age"),24);
            List<Predicate> list=newArrayList<>();
            list.add(name);
            list.add(age);
            Predicate[] pre=newPredicate[list.size()];//将list中的数据注入到一个Predicate类型的数组中,其中or是或者的关系,and是并列的关系return criteriaBuilder.or(list.toArray(pre));}};
    List list= repositoryJpaSe.findAll(spe);
    System.out.println(list);}//多条件查询并且排序@TestpublicvoidtestJpaSpe1(){
        Specification spe=newSpecification(){@Overridepublic PredicatetoPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder){//注意可以这样来写我们的多个条件,这样写比较方便简洁return criteriaBuilder.or(criteriaBuilder.equal(root.get("name"),"张三丰"),criteriaBuilder.equal(root.get("age"),333),criteriaBuilder.equal(root.get("id"),2));}};
        Sort sort=Sort.by(Sort.Direction.DESC,"id");
        List list= repositoryJpaSe.findAll(spe, sort);
        System.out.println(list);}//多条件查询并且分页查询@TestpublicvoidtestJpaSpe2(){
    Specification spe=newSpecification(){@Overridepublic PredicatetoPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder){//注意可以将and和or条件组合使用return criteriaBuilder.or(criteriaBuilder.equal(root.get("name"),"张三丰"),criteriaBuilder.equal(root.get("age"),333),criteriaBuilder.equal(root.get("id"),2));}};
    Sort sort=Sort.by(Sort.Direction.DESC,"id");
    PageRequest pageable=PageRequest.of(0,1,sort);
    Page<Person> people= repositoryJpaSe.findAll(spe,pageable);
    List<Person> list= people.getContent();
    System.out.println(list);}

关联映射操作

一对多的关联映射

要在一对多和多对一的实体类中分别加注解

实体类代码

//roles   角色的实体类@Entity@Table(name="tb_roles")publicclassRoles{@Id@GeneratedValue(strategy= GenerationType.IDENTITY)@Column(name="roles_id")private Integer roles_id;@Column(name="role_name")
  • 作者:只会CTRL CV的菜鸡
  • 原文链接:https://blog.csdn.net/lyq1525761478/article/details/115732890
    更新时间:2022年8月2日12:15:48 ,共 8832 字。