首页技术栈归档照片墙音乐日记随想收藏夹友链留言关于

Spring-Data-jpa

写作时间:2026-07-08

Spring-Data-jpa基本介绍

什么是spring-data-jpa

 可以理解为JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL(Java Persistence Query Language)查询语言,属于Spring整个生态体系的一部分。随着Spring Boot和Spring Cloud在市场上的流行,Spring Data JPA也逐渐进入大家的视野,它们组成有机的整体,使用起来比较方便,加快了开发的效率,使开发者不需要关心和配置更多的东西,完全可以沉浸在Spring的完整生态标准实现下。JPA上手简单,开发效率高,对对象的支持比较好,又有很大的灵活性,市场的认可度越来越高。

  ********JPA是Java Persistence API的简称,********中文名为Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

  JPA包括以下3方面的内容:

  (1)一套API标准。在javax.persistence的包下面,用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从烦琐的JDBC和SQL代码中解脱出来。

  (2)面向对象的查询语言:Java Persistence QueryLanguage(JPQL)。这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密*****耦合***

  (3)ORM(object/relational metadata)元数据的映射。JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。

Spring Data介绍

 Spring Data项目是从2010年发展起来的,从创立之初SpringData就想提供一个大家熟悉的、一致的、基于Spring的数据访问编程模型,同时仍然保留底层数据存储的特殊特性。它可以轻松地让开发者使用数据访问技术,包括关系数据库、非关系数据库(NoSQL)和*****基于云的数据服务。*** 

  Spring Data Common是Spring Data所有模块的公用部分,该项目提供跨Spring数据项目的共享基础设施。它包含了技术中立的库接口以及一个坚持java类的元数据模型。

  *Spring Data不仅对传统的数据库访问技术JDBC、Hibernate、JDO、TopLick、JPA、Mybitas做了很好的支持、扩展、抽象、提供方**便的API,还对NoSQL等非关系数据做了很好的支持,包括MongoDB、***Redis、Apache Solr等

Spring Data操作的主要特性

  Spring Data项目旨在为大家提供一种通用的编码模式。数据访问对象实现了对物理数据层的抽象,为编写查询方法提供了方便。通过对象映射,实现域对象和持续化存储之间的转换,而模板提供的是对底层存储实体的访问实现。如图1-4所示。操作上主要有如下特征:

  提供模板操作,如Spring Data Redis和Spring Data Riak。

  强大的Repository和定制的数据存储对象的抽象映射。   对数据访问对象的支持(Auting等)。

Spring-Data-JPA的结构图

  七个Repository接口:

    1. Repositoryspring-data-jpa结构图

    2. CrudRepository

    3. PagingAndSortingRepository

    4. QueryByExampleExecutor

    5. JpaRepository

    6. JpaSpeccificationExecutor

    7. QueryDslPredicateExecutor

  两个实现类:

    1. SimpleJpaRepository

    2. QueryDslJpaRepository

  关系结构图如图1-5所示。

spring-data-jpa使用

快速上手

导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

编写配置文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/news?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    password: root
    username: root
  jpa:
    show-sql: true
    database: mysql
    hibernate:
      ddl-auto: update
      naming:
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl 
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl  #驼峰命名

NewsEntity.java

package com.springdatajpa2.pojo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;

@Entity  //表示是一个实体类
@Table(name = "news", schema = "newsdb", catalog = "")
@JsonIgnoreProperties(value={"hibernateLazyInitializer"})  //转json对象忽略空值
public class NewsEntity {
    private int id;
    private String typeId;
    private String title;
    private String publisher;
    private String publisherFace;
    private String content;
    private Timestamp createTime;
    private Timestamp updateTime;
    private Integer deleted;

    @Id  //主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//指定主机的生成策略
    @Column(name = "id")  //指定字段和实体类属性的映射关系

     public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "type_id")
    public String getTypeId() {
        return typeId;
    }

    public void setTypeId(String typeId) {
        this.typeId = typeId;
    }

    @Basic
    @Column(name = "title")
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Basic
    @Column(name = "publisher")
    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    @Basic
    @Column(name = "publisher_face")
    public String getPublisherFace() {
        return publisherFace;
    }

    public void setPublisherFace(String publisherFace) {
        this.publisherFace = publisherFace;
    }

    @Basic
    @Column(name = "content")
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Basic
    @Column(name = "create_time")
    public Timestamp getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Timestamp createTime) {
        this.createTime = createTime;
    }

    @Basic
    @Column(name = "update_time")
    public Timestamp getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Timestamp updateTime) {
        this.updateTime = updateTime;
    }

    @Basic
    @Column(name = "deleted")
    public Integer getDeleted() {
        return deleted;
    }

    public void setDeleted(Integer deleted) {
        this.deleted = deleted;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        NewsEntity that = (NewsEntity) o;
        return id == that.id &&
                Objects.equals(typeId, that.typeId) &&
                Objects.equals(title, that.title) &&
                Objects.equals(publisher, that.publisher) &&
                Objects.equals(publisherFace, that.publisherFace) &&
                Objects.equals(content, that.content) &&
                Objects.equals(createTime, that.createTime) &&
                Objects.equals(updateTime, that.updateTime) &&
                Objects.equals(deleted, that.deleted);
    }

    @Override
    public String toString() {
        return "NewsEntity{" +
                "id=" + id +
                ", typeId='" + typeId + '\'' +
                ", title='" + title + '\'' +
                ", publisher='" + publisher + '\'' +
                ", publisherFace='" + publisherFace + '\'' +
                ", content='" + content + '\'' +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", deleted=" + deleted +
                '}';
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, typeId, title, publisher, publisherFace, content, createTime, updateTime, deleted);
    }
}

NewsDao.java

package com.springdatajpa2.dao;
import com.springdatajpa2.pojo.NewsEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import java.util.List;

public interface NewsDao extends JpaRepository<NewsEntity,Integer> ,
        JpaSpecificationExecutor<NewsEntity> {

}            

newsService.java

package com.springdatajpa2.service;
import com.springdatajpa2.pojo.NewsEntity;
import java.util.List;
public interface NewsService {

    /**
     * 添加新闻
     */
    NewsEntity saveNews(NewsEntity newsEntity);

    /**
     * 修改新闻
     */
    NewsEntity updateNews(NewsEntity newsEntity);
}    

NewsServiceImpl.java

package com.springdatajpa2.service.impl;
import com.springdatajpa2.dao.NewsDao;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Transactional
public class NewsServiceImpl implements NewsService {

    @Autowired
    private NewsDao newsDao;

    /**
     * 添加新闻
     *
     * @param newsEntity
     */
    @Override
    public NewsEntity saveNews(NewsEntity newsEntity) {
        return newsDao.save(newsEntity);
    }

    /**
     * 修改新闻
     *
     * @param newsEntity
     */
    @Override
    public NewsEntity updateNews(NewsEntity newsEntity) {
        return newsDao.save(newsEntity);
    }
}    

测试类

package com.springdatajpa2;

import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class SpringDataJpa2ApplicationTests {

    @Autowired
    private NewsService newsService;

    /**
     * 新增
     */
    @Test
    void contextLoads() {
        NewsEntity newsEntity = new NewsEntity();
        newsEntity.setTypeId("1111");
        newsEntity.setTitle("hhhhh");
       newsService.saveNews(newsEntity);
    }

    /**
     * 修改
     */
    @Test
    void contextLoads2() {
        NewsEntity newsEntity = new NewsEntity();
        newsEntity.setId(25);
        newsEntity.setTypeId("1111");
        newsEntity.setTitle("aaa");
        newsService.updateNews(newsEntity);
    }
}    

方法命名查询

①查询的方法:find或get或read开头

②查询条件:用关键字链接,涉及属性首写字母大写

具体的查询方法命名规范如下: 1.findBy+属性名称(属性名称首字母大写,这种格式只能生成等值的查询条件) 举例:findByUserName=>select * from customer where userName=? 2.findBy+属性名称+查询方式(Like|IsNull|Equals|Between|LessThan|GreaterThan|OrderBy|Not|In等) 3.多条件查询:findBy+属性名称1+查询方式1+属性名称2+查询方式2[...]

举例:

getByIdAndUsername(int id,String username);
getById(int id);
getByIdLessThanEqual(int id);
getByGreaterThanEqual(int id);
getByUsernameLike(String str);
getByUsernameContaining(string str)

newsDao

package com.springdatajpa2.dao;
import com.springdatajpa2.pojo.NewsEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;

public interface NewsDao extends JpaRepository<NewsEntity,Integer> ,
        JpaSpecificationExecutor<NewsEntity> {

    /*
    以find开头
  根据标题查询命名有规范
 */
    List<NewsEntity> findByTitleLike(String title);

    /**
    以find开头
     * 根据id查询
     */
    NewsEntity findById(int id);
        }            

NewsService

package com.springdatajpa2.service;
import com.springdatajpa2.pojo.NewsEntity;
import java.util.List;
public interface NewsService {

 /*
   根据标题查询
  */
  List<NewsEntity>  findByTitleLike(String title);

    /**
     * 根据编号查询
     */
    NewsEntity findById(int id);
}    

NewsServiceImpl

package com.springdatajpa2.service.impl;
import com.springdatajpa2.dao.NewsDao;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class NewsServiceImpl implements NewsService {
        @Autowired
    private NewsDao newsDao;
    /**
    根据标题模糊查询
    */
    @Override
    public List<NewsEntity> findByTitleLike(String title) {
        return newsDao.findByTitleLike("%"+title+"%");
    }

    /**
     * 根据编号查询
     *
     * @param id
     */
    @Override
    public NewsEntity findById(int id) {
        return newsDao.findById(id);
    }
}    

测试类

package com.springdatajpa2;

import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class SpringDataJpa2ApplicationTests {

    @Autowired
    private NewsService newsService;

    /**
     * 根据标题模糊查询
     */
    @Test
    void contextLoads3() {
        List<NewsEntity> 药 = newsService.findByTitleLike("药");
        for (NewsEntity newsEntity : 药) {
            System.out.println(newsEntity.toString());
        }
    }
    /**
     * 根据编号查询
     */
    @Test
    void contextLoads4() {
        System.out.println(newsService.findById(10).toString());
    }

}    

多表查询

实体类

    private Type type;

    @ManyToOne(fetch = FetchType.EAGER)//多对一
    @JoinColumn(name = "typeId",referencedColumnName = "id")  //typeId对应实体的typeId   id对应type类的id
    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

NewsSwevice

    /**
     * 连表查询
     * @return
     */
    List<NewsEntity> findByTitle(String title);

NewsServiceImpl

    /**
     * 连表查询
     * @return
     */
    @Override
    public List<NewsEntity> findByTitle(String title) {
        NewsEntity newsEntity=new NewsEntity();
        newsEntity.setTitle(title); 
        //newsEntity.setType(type);
        //Type type = new Type();
        ExampleMatcher title1 = ExampleMatcher.matching().withMatcher("title",
                ExampleMatcher.GenericPropertyMatchers.contains());//模糊查询如果没有可以直接不要
        Example<NewsEntity> entityExample=Example.of(newsEntity,title1);  
        return newsDao.findAll(entityExample);
    }

测试类

    /**
     * 多表查询
     *
     */
    @Test
    void contextLoads7() {
        List<NewsEntity> 药 = newsService.findByTitle("");
        for (NewsEntity newsEntity : 药) {
            System.out.println(newsEntity.toString());
        }
    }

Query和Modifying注解

Query注解

jpql : 全称Java Persistence Query Language java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将JPQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。 其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的字段

举例:(from 类名 where 属性...)

select c from Customer c 或 select c from Customer as c 或 from Customer from Customer c where c.id = 1 from Customer c order by c.id desc (没有select,表示查询所有属性) select c.id, c.custName, c.custSource from Customer c select count(c.id) from Customer c group by cust_industry select max(c.id) from Customer c

前面说了,使用Spring-data-jpa进行开发的过程中,常用的功能,我们几乎不需要写一条jpql语句,复杂的功能,我们才需要自己写jpql语言。

自己写jpql语言就是通过@query注解来实现的:

  1. 没参数的@query查询:实现查找News中id最大的哪个记录返回相应对象:
@Query("select n from News n where n.id=(select max(ne.id) from News ne)")
News findNewsByMaxId();
  1. 带参数的@query查询,使用占位符:

    @Query("select n from News n where n.title = ?1")
    List<News> findNewsByTitle(String title);
    
  2. 带参数的@query查询,使用命名参数:

    @Query("select n from News n where n.title = :title and n.publisher = :publisher")
    List<News> findNewsByTitleAndPublisher(String title, String publisher);
    
  3. 带参数的@query查询,使用like的时候,是可以用%的,前面讲mybatis是不可以的但springdata可以:

    @Query("select n from News n where n.title = :title and n.publisher like %:publisher%")
    List<News> findNewsByTitleAndPublisherLike(String title, String publisher);
    
  4. 使用@query执行原生的sql查询:

    @Query(value = "select * from news",nativeQuery = true)
    List<News> findAllByNativeQuery();
    

Modifying注解

在@Query注解的上面加上@Modifying,那么就可以执行update和delete的jpql语句了:

@Modifying
@Query("update News set title=?1 where id=?2")
void updateNews(String title, Integer id);

注意:直接执行这个方法是不行的,必须在service层里调用它才可以,原因是Springdata执行update和delete语句需要可写事务支持的,我们事务是放在service层的!Springdata需要事务,那么为什么前面的查询可以直接执行呢?默认情况下Springdata也是有事务的,只不过这个事务是只读事务,不能修改和删除数据库里的记录。另外还要注意一个问题,注解@Modifying是不能做insert语句的,jpql不支持!

NewsDao

package com.springdatajpa2.dao;
import com.springdatajpa2.pojo.NewsEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;

public interface NewsDao extends JpaRepository<NewsEntity,Integer> ,
        JpaSpecificationExecutor<NewsEntity> {
    /**
     * 根据标题和发布人查询,1代表第一个参数title,2代表第二个参数publisher
     */
    @Query("from NewsEntity where  title like %?1% and publisher=?2")
    List<NewsEntity> getNewsEntityList(String title,String publisher);


    /**
     * 根据id修改标题
     */
    @Modifying //根据id进行修改  不能写新增
    @Query("update NewsEntity set title=?1 where id=?2")
    void updateNewsEntityById(String title,int id);
}

NewsService

package com.springdatajpa2.service;
import com.springdatajpa2.pojo.NewsEntity;
import java.util.List;
public interface NewsService {    
/**
     * 根据标题和发布人查询
     */
    List<NewsEntity> getNewsEntityList(String title,String publisher);
    /**
     * 根据id修改标题
     */
    void updateNewsEntityById(String title,int id);
}    

NewsServiceImpl

package com.springdatajpa2.service.impl;
import com.springdatajpa2.dao.NewsDao;
import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class NewsServiceImpl implements NewsService {

    @Autowired
    private NewsDao newsDao;
    /**
     * 根据标题和发布人查询
     */
        @Override
    public List<NewsEntity> getNewsEntityList(String title, String publisher) {
        return newsDao.getNewsEntityList(title, publisher);
    }

    /**
     * 根据id修改标题
     *
     * @param title
     * @param id
     */
    @Override
    public void updateNewsEntityById(String title, int id) {
        newsDao.updateNewsEntityById(title, id);
    }


}

测试类

package com.springdatajpa2;

import com.springdatajpa2.pojo.NewsEntity;
import com.springdatajpa2.service.NewsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class SpringDataJpa2ApplicationTests {

    @Autowired
    private NewsService newsService;
        /**
     * 标题和发布人查询
     */
    @Test
    void contextLoads5() {
        List<NewsEntity> newsEntityList = newsService.getNewsEntityList("药", "科泰学院");
        for (NewsEntity newsEntity : newsEntityList) {
            System.out.println(newsEntity.toString());
        }
    }
    /**
     * 根据id修改标题
     *
     */
    @Test
    void contextLoads6() {
       newsService.updateNewsEntityById("bbb",25);

    }
}

Spring-Data-Jpa分页查询排序

创建一个新的接口,继承PagingAndSortingRepository 接口,在接口中无需定义任何方法

public interface PageNewsRepository extends PagingAndSortingRepository<News,Integer> {

}

分页查询



@Override
public List<News> findAllByPage(Integer pageNum, Integer pageSize) {
    //分页默认从0开始
    Pageable pageable = PageRequest.of(pageNum-1, pageSize);
    Page<News> page = pageNewsRepository.findAll(pageable);
    System.out.println("当前页:"+page.getNumber()+1);
    System.out.println("每页数量:"+page.getSize());
    System.out.println("总页数:"+page.getTotalPages());
    System.out.println("总记录数:"+page.getTotalElements());
    System.out.println("当前记录:"+page.getContent());
    return page.getContent();

}

排序

@Override
public List<News> findAllBySort() {
    List<News> newsList = new ArrayList<>();
    //按id降序
    Sort sort = Sort.by(Sort.Direction.DESC, "id");
    Iterable<News> newsIterable = pageNewsRepository.findAll(sort);
    Iterator<News> iterator = newsIterable.iterator();
    while (iterator.hasNext()) {
        newsList.add(iterator.next());
    }
    return newsList;
}

先排序后分页

public List<News> findAllBySortAndPage() {
    Integer pageNum=1;
    Integer pageSize=5;
    // Sort.Direction.DESC  排序规则      id: 用哪一个字段来排序
    Sort sort = Sort.by(Sort.Direction.DESC, "id");
    PageRequest pageable=PageRequest.of(pageNum-1,pageSize,sort);
    Page<News> page = pageNewsRepository.findAll(pageable);

    System.out.println("当前页 :" + page.getNumber() + 1);
    System.out.println("每页显示数量:" + page.getSize());
    System.out.println("总页数:" + page.getTotalPages());
    System.out.println("总记录数:" + page.getTotalElements());
    System.out.println("当前记录:" + page.getContent());
    return page.getContent();
}

aa

有多个字段需要排序的时候

public List<News> findAllBySortAndPage() {
    Integer pageNum=1;
    Integer pageSize=5;

    // Sort.Direction.DESC  排序规则      id: 用哪一个字段来排序
    List<Sort.Order>  orders= new ArrayList<>();
    Sort.Order order1=new Sort.Order(Sort.Direction.DESC,"id");
    Sort.Order order2=new Sort.Order(Sort.Direction.DESC,"name");
    orders.add(order1);
    orders.add(order2);
    Sort sort = Sort.by(orders);

    PageRequest pageable=PageRequest.of(pageNum-1,pageSize,sort);
    Page<News> page = pageNewsRepository.findAll(pageable);

    System.out.println("当前页 :" + page.getNumber() + 1);
    System.out.println("每页显示数量:" + page.getSize());
    System.out.println("总页数:" + page.getTotalPages());
    System.out.println("总记录数:" + page.getTotalElements());
    System.out.println("当前记录:" + page.getContent());
    return page.getContent();
}

JpaRepository接口

创建JpaNewsRepository接口,继承JpaRepository接口,无需添加任何方法

public interface JpaNewsRepository extends JpaRepository<News, Integer> {

}
public void saveNews() {
        News news = new News();
        news.setTitle("这是一条没有灵魂的测试数据");
        news.setContent("没有灵魂没有灵魂");
        news.setTypeId("1001");
    //有则修改,无则添加
        jpaNewsRepository.saveAndFlush(news);
    }

JpaSpecificationExecutor接口

paSpecificationExecutor这个接口和Repository接口不是一个家族的,它是用对象来写jpql语句的一个接口,内部的操作其实就是CriteriaQuery这种查询方法,JpaSpecificationExecutor接口里有下面的这些方法:

修改JpaNewsRepository的父接口如下:

public interface JpaNewsRepository extends JpaRepository<News, Integer>, JpaSpecificationExecutor<News> {

}

Java中类是不可以有多个父类的,但是接口是可以有多个父接口的

简单举一个例子,获取id>10的新闻记录:

public List<News> findCustomerAll(Integer id) {
    /**  Root : 要查询的实体类
     *   CriteriaQuery:   query对象,基本上不用
     *   CriteriaBuilder: 构建的条件和条件连接词
     */

    // 创建接口对象的内部类
    Specification specification = new Specification<News>() {
        @Override
        public Predicate toPredicate(Root<News> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
            Path<Integer> path = root.get("id");
            Predicate predicate = criteriaBuilder.lessThan(path, id);
            return predicate;
        }
    };
    return jpaNewsRepository.findAll(specification);

}

实现分页和动态条件查询效果:

1、dao层继承接口 JpaRepository<T,ID>和JpaSpecificationExecutor,无其他操作

public interface JpaNewsRepository extends JpaRepository<News, Integer>,JpaSpecificationExecutor<News> {


}

2、在service层添加动态条件查询的方法

@Override
    public List<News> findAllByParam(News news, Integer pageNum) {
        List<News> resultList = null;
        Specification<News> querySpecifi = new Specification<News>() {
            @Override
            public Predicate toPredicate(Root<News> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                if (StringUtils.hasText(news.getTitle())) {
                    predicates.add(cb.like(root.get("title"), news.getTitle()));
                }
                if (StringUtils.hasText(news.getPublisher())) {
                    predicates.add(cb.equal(root.get("publisher"), news.getPublisher()));
                }
                // and到一起的话所有条件就是且关系,or就是或关系
                return cb.and(predicates.toArray(new Predicate[0]));
            }
        };
        PageRequest   pageable= PageRequest.of(pageNum-1, 3);
        resultList = this.jpaNewsRepository.findAll(querySpecifi,pageable).getContent();
        return resultList;

    }

3、controller层调用service层的方法

@GetMapping(value = "/findallbyparam")
public String findAll(News news, Integer pageNum) throws JsonProcessingException {
    List<News> newsList = newsService.findAllByParam(news, pageNum);
    return objectMapper.writeValueAsString(newsList);
}
avatar

yuanyourdomain

写代码,做研究,记录生活。

RECOMMENDED

MyBatis 动态 SQL

2026-07-08

Nginx 基础入门

2026-07-08

Maven 多模块与私服

2026-07-08