68、Spring Data JPA 的 方法名关键字查询(全自动,既不需要提供sql语句,也不需要提供方法体)

news2024/11/27 0:49:34

1、方法名关键字查询(全自动,既不需要提供sql语句,也不需要提供方法体)
2、@Query查询(半自动:提供 SQL 或 JPQL 查询)
3、自定义查询(全手动)

★ 方法名关键字查询(全自动)

(1)继承 CrudRepository 接口 的 DAO 组件可按特定规则来定义查询方法,
     只要这些查询方法的 方法名 遵守特定的规则,
     Spring Data 将会自动为这些方法生成 查询语句、提供 方法实现体。

(2)方法名关键字的查询方法
     能以 find...By、read...By、query…By、count…By(查询记录的条数)、get…By开头,
     并在方法名中嵌入特定关键字即可,Spring Data就会自动生成相应的查询方法体。

▲ 关键字规则

 在方法名中将属性名、运算符都设计成关键字,比如如下:
 - findByName(String name),这表明根据name属性执行查询。
 - findByAgeGreaterThan(int age):表明查询age属性大于指定值的记录。

▲ 关键字方法中同样可定义Pagable、Sort参数,用于控制分页和排序。

 说明:如果要做分页或排序的查询,
 其实没必须要去继承PagingAndSortingRepository,继承CrudRepository也是可行的

▲ 需要说明的情况:

 一种情况需要说明,对比如下两个方法:
 - findByAddressAndZip:该方法要根据address和zip两个属性进行查询,
   它对应的JPQL片段为:... where x.address = ?1 and zip = ?2。

 - findByAddressZip:留意该方法名的Address和Zip之间既没有And,也没有Or,
   那就表明用的是“属性路径”方式,表明该方法要根据address属性的zip属性进行查询,
   它对应的JPQL片段为:... where x.address.zip = ?1。


如果你的方法名中的关键字写错了,往往就会报QueryCreateException。

代码演示:

数据库数据

在这里插入图片描述

创建对应的两个实体类。
Student实体类
这节用到的一些类和配置文件
在这里插入图片描述

Clazz 实体类
在这里插入图片描述

//根据班级名称查询对象–ClazzDao

方法
在这里插入图片描述
测试结果
在这里插入图片描述

//根据班级名称模糊查询–ClazzDao

方法:
在这里插入图片描述

测试结果
在这里插入图片描述

查询年龄大于指定参数的学生–StudentDao

方法:
在这里插入图片描述

测试结果:
在这里插入图片描述

根据年龄和班级名称查询学生–StudentDao

在这里插入图片描述

方法:
在这里插入图片描述

测试结果:

在这里插入图片描述

根据地址后缀进行分页查询,查询 address 带有 “洞” 的学生并进行分页 – StudentDao

在这里插入图片描述

结果:
在这里插入图片描述
在这里插入图片描述

完整代码

Student

package cn.ljh.app.domain;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

/**
 * strategy:策略 , GenerationType:生成类型  , Column:列
 */

//修饰该类成为实体类
@Entity
@Getter
@Setter
//表示该类映射到数据库的student_inf表
@Table(name = "student_inf")
public class Student
{
    @Id //设置为主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增策略
    @Column(name = "student_id") //该属性名映射到数据库表的列名
    private Integer id;

    private String name;
    private int age;
    private String address;
    private char gender;

    //关联关系,多个学生对应一个教室
    //targetEntity:指定关联实体的类型,不指定也没问题,底层会通过反射去识别
    @ManyToOne(targetEntity = Clazz.class)
    //JoinColumn: name = "clazz_code"  ,映射外键列列名 ,这个"clazz_code "是指映射的 Clazz 类中的成员变量
    //referencedColumnName = "clazz_code" ,这个"clazz_code" 是指表的列名
    //referencedColumnName: --> name = "clazz_code"这个外键列名引用到对方的数据表(clazz_inf)的列名叫"clazz_code"
    @JoinColumn(name = "clazz_code",referencedColumnName = "clazz_code")
    private Clazz clazz;

    @Override
    public String toString()
    {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", gender=" + gender +
                '}';
    }
}

Clazz

package cn.ljh.app.domain;


import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;


@Entity //修饰该类为实体类
@Table(name = "clazz_inf") //该实体类映射到数据库的 clazz_inf 表
@Getter
@Setter
public class Clazz
{
    @Id//主键id
    @Column(name = "clazz_code") //表示这个属性在数据库表中的列名叫这个clazz_code
    @GeneratedValue(strategy = GenerationType.IDENTITY) //主键id的自增策略
    private Integer clazz_code; //班级号
    private String name;  //班级名称

    //关联关系,一个教室对应多个学生
    //targetEntity:指定关联实体的类型,不指定也没问题,底层会通过反射去识别
    //mappedBy 属性(clazz) 关联实体(Student)中,哪个属性(student.clazz)引用到当前实体(Student实体)
    @OneToMany(targetEntity = Student.class,mappedBy = "clazz")
    private Set<Student> students = new HashSet<>();

    @Override
    public String toString()
    {
        return "Clazz{" +
                "clazz_code=" + clazz_code +
                ", name='" + name + '\'' +
                '}';
    }
}

ClazzDao

package cn.ljh.app.dao;

import cn.ljh.app.domain.Clazz;
import org.springframework.data.repository.CrudRepository;

import java.util.List;


//CrudRepository 的第一个泛型参数是被操作的实体类型,第二个参数是实体的主键类型
//方法名关键字查询: Spring Data 会自动生成查询语句、生成查询方法体
public interface ClazzDao extends CrudRepository<Clazz, Integer>
{
    //根据班级名称查询对象
    Clazz findByName(String name);

    //根据班级名称模糊查询
    List<Clazz> findByNameLike(String namePattern);


}

StudentDao

package cn.ljh.app.dao;

import cn.ljh.app.domain.Student;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

//CrudRepository 的第一个泛型参数是被操作的实体类型,第二个参数是实体的主键类型
public interface StudentDao extends CrudRepository<Student,Integer>
{
    //查询年龄大于指定参数的学生
    List<Student> findByAgeGreaterThan(int startAge);

    //根据年龄和班级名称查询学生
    //Age 和 ClazzName 用 And 连接起来,表示两个查询条件,
    //ClazzName这两个单词中间没有And连接起来,表示是一个路径写法,表示是Clazz类的name属性
    List<Student> findByAgeAndClazzName(int age , String clazzName);

    //根据地址后缀进行分页查询,查询 address 带有 "洞" 的学生并进行分页
    Page<Student> findByAddressEndingWith(String addrSuffix, Pageable pageable);
    
}

ClazzDaoTest

package cn.ljh.app.dao;


import cn.ljh.app.domain.Clazz;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

//SpringBootTest.WebEnvironment.NONE : 表示不需要web环境
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class ClazzDaoTest
{
    @Autowired
    private ClazzDao clazzDao;

    //参数化测试
    @ParameterizedTest
    //参数只有一个的测试用 @ValueSource
    //根据班级名称查询对象
    @ValueSource(strings = {"超级A营","超级B班","aaa"})
    public void testFindByName(String name)
    {
        Clazz clazz = clazzDao.findByName(name);
        System.err.println(clazz);
    }

    @ParameterizedTest
    //根据班级名称模糊查询
    @ValueSource(strings = {"超级%","%营"})
    public void testFindByNameLike(String namePattern)
    {
        List<Clazz> clazzes = clazzDao.findByNameLike(namePattern);
        clazzes.forEach(System.err::println);
    }


}

StudentDaoTest

package cn.ljh.app.dao;


import cn.ljh.app.domain.Student;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import java.util.List;

//SpringBootTest.WebEnvironment.NONE : 表示不需要web环境
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class StudentDaoTest
{
    @Autowired
    private StudentDao studentDao;

    /**
     * @ValueSource: 每次只能传一个参数
     * @CsvSource:每次可以传多个参数
     */

    //需求:查询年龄大于指定参数的记录
    //参数化测试
    @ParameterizedTest
    @ValueSource(ints = {20, 200})
    public void testFindByAgeGreaterThan(int startAge)
    {
        List<Student> students = studentDao.findByAgeGreaterThan(startAge);
        students.forEach(System.err::println);
    }

    //根据年龄和班级名称查询学生
    //Age 和 ClazzName 用 And 连接起来,表示两个查询条件,
    //ClazzName这两个单词中间没有And连接起来,表示是一个路径写法,表示是Clazz类的name属性
    @ParameterizedTest
    //参数一个是int,一个是String,这个注解在传参的时候会自动进行类型转换
    @CsvSource(value = {"20,超级A营", "18,超级D班"})
    public void testFindByAgeAndClazzName(int age, String clazzName)
    {
        List<Student> students = studentDao.findByAgeAndClazzName(age, clazzName);
        students.forEach(System.err::println);
    }


    //pageNo: 要查询哪一页的页数 , pageSize: 每页显示的条数
    @ParameterizedTest
    @CsvSource({"洞,2,3","洞,1,4","洞,3,2"})
    public void testFindByAddressEndingWith(String addrSuffix, int pageNo, int pageSize)
    {
        //分页对象,此处的pageNo是从0开始的,0代表第一页,所以这里的 pageNo 要 -1
        Pageable pageable1 = PageRequest.of(pageNo - 1, pageSize);
        Page<Student> students = studentDao.findByAddressEndingWith(addrSuffix, pageable1);

        int number = students.getNumber() + 1;
        System.err.println("总页数:" + students.getTotalPages());
        System.err.println("总条数:" + students.getTotalElements());
        System.err.println("当前第:" + number + " 页");
        System.err.println("当前页有:" + students.getNumberOfElements() + " 条数据");
        students.forEach(System.err::println);
    }
}

application.properties

# 配置连接数据源,这些配置由 DataSourceProperties 类负责处理---
# SpringBoot 读取到这些配置信息后,会使用 AutoConfiguration 去容器中自动配置 DataSource Bean
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

# 针对 HikariCP 进行详细配置---
# 指定连接池最大只能有20个连接
#spring.datasource.hikari.maximum-pool-size=20

# 配置 JPA 相关属性,由 JpaProperties 类负责处理---
# SpringBoot 读取到这些配置信息后,会使用 AutoConfiguration 去容器中自动配置 EntityManagerFactory Bean
# JPA 底层就是依赖这个 EntityManagerFactory

# 自动建表,只能true或者false
# spring.jpa.generate-ddl=true
# 这个也是自动建表,不过比spring.jpa.generate-ddl更严谨,作用:如果已有数据表,无需创建,否则创建数据表
spring.jpa.hibernate.ddl-auto=update
# 指定操作的数据库
spring.jpa.database=mysql
# 是否在执行的时候显示sql语句
spring.jpa.show-sql=true

db.sql

drop database springboot;
create database springboot;
use springboot;
-- 创建clazz_inf表
create table clazz_inf
(
    clazz_code int primary key auto_increment,
    name varchar(255)
);
-- 创建student_inf表
create table student_inf
(
    student_id int primary key auto_increment,
    name varchar(255),
    age int,
    address varchar(255),
    gender char(2),
    clazz_code int,
    foreign key(clazz_code) references clazz_inf(clazz_code)
);
-- 向clazz_inf表插入数据
insert into clazz_inf
values
(null, '疯狂Java训练营'),
(null, '疯狂Java就业班'),
(null, '疯狂Java基础班'),
(null, '疯狂Java提高班');

-- 向student_inf表插入数据
insert into student_inf
values
(null, '孙悟空', 500, '花果山水帘洞', '男', 1),
(null, '牛魔王', 800, '积雷山摩云洞', '男', 1),
(null, '猪八戒', 600, '福陵山云栈洞', '男', 2),
(null, '沙和尚', 580, '流沙河', '男', 3),
(null, '白鼠精', 23, '陷空山无底洞',  '女', 2),
(null, '蜘蛛精', 18, '盘丝岭盘丝洞', '女', 4),
(null, '玉面狐狸', 21, '积雷山摩云洞', '女', 3),
(null, '杏仙', 19, '荆棘岭木仙庵', '女', 4);

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
    </parent>
    <groupId>cn.ljh</groupId>
    <artifactId>spring_data_jpa_keyword</artifactId>
    <version>1.0.0</version>
    <name>spring_data_jpa_keyword</name>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1019923.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信超实用的隐藏功能:群发上千人,定时发圈,自动回复,一键转发朋友圈

多账号聚合 企业可将员工的工作微信聚合到系统上管理&#xff0c;在同一个页面就能同时收发多个微信的消息&#xff0c;无需频繁地切换设备与账号。将微信号分配给对应的员工&#xff0c;可对已有微信号进行监管。 群发无限制 微信自带的群发是有200人数限制的&#xff0c;对于…

android 点9记录

记录一个9点的4个边作用&#xff0c;左上表示拉伸的区域&#xff0c;需要2边都有黑点&#xff0c;如果只有一边&#xff0c;运行起来会有奇怪的投影&#xff0c;右边和下边默认拉满即可。

无涯教程-JavaScript - MUNIT函数

描述 MUNIT函数返回指定尺寸的单位矩阵。 语法 MUNIT (dimension)争论 Argument描述Required/OptionalDimension Dimension是一个整数,指定要返回的单位矩阵的尺寸。 尺寸必须大于零。 Required Notes MUNIT返回一个数组。因此,应将其作为数组公式输入 MUNIT (N)$\begin{m…

朴素贝叶斯案例分析

贝叶斯模型是利用先贝叶斯定理进行计算的一种机器学习模型&#xff0c;并且此处涉及先验概率和后验概率。比如我们都知道去赌场会十赌九输&#xff0c;此是以前的经验&#xff0c;即为先验概率&#xff0c;也或者大家都知道抛硬币时上下面第一次都是1/2概率&#xff0c;这均为先…

如何制作一篇公众号推文?纯干货

公众号推文是一种通过微信公众号平台向用户传播信息和内容的方式&#xff0c;具有广泛的受众群体和良好的传播效果。下面伯乐网络传媒给大家分享关于如何制作一篇公众号推文的一些建议和步骤&#xff0c;建议收藏起来慢慢看&#xff01; 确定目标受众&#xff1a;在开始制作推文…

Matlab编程中函数的重命名方法

Matlab编程中函数的重命名方法 在进行matlab编程时候&#xff0c;有时需要根据自己的习惯&#xff0c;需要对函数重命名。本文简要介绍重命名的方法。 一、重命名的方法 通过和赋值号实现&#xff0c;如下所示&#xff1a; 新函数名原函数名二、具体举例 clc clear all %将…

第二章-H3C-网络设备操作入门

6.2 路由器与交换机的作用与特点 6.2.1 路由器的作用与特点 路由器的作用 1.连接具有不同介质的链路 2.连接网络或子网&#xff0c;隔离广播 3.对数据报文执行寻址和转发 4.交换和维护路由信息 6.2.2 交换机的作用与特点 交换机的作用 1.连接多个以太网物理网段&#xff0c;隔…

武汉凯迪正大—雷电冲击电压发生器

雷电冲击电压发生器系统特点 1&#xff0e;采用PLC可编程控制器技术&#xff0c;使控制系统实现超小型化及高可靠性能的智能自动控制和测量&#xff1b;配合我公司的数字化测控系统方便的与计算机连接&#xff0c;实现计算机智能自动控制、测量和管理 。 2&#xff0e;输出极…

不负昭华,前程似锦,新一批研发效能认证证书颁发丨IDCF

亲爱的认证学员&#xff0c; 恭喜你成功获得由国家工业和信息化部教育与考试中心颁发的职业技术证书——《研发效能(DevOps)工程师国家职业技术认证》。你的努力和才华得到了官方的认可&#xff0c;这是你职业生涯中的一个重要的里程碑。 这个证书不仅代表着你的专业知识和技…

JeecgBoot 低代码安装 运行开发

技术文档 技术官网&#xff1a; http://www.jeecg.com在线演示 &#xff1a; http://boot.jeecg.com标签 &#xff1a;BasicTable 表格 - JeecgBoot 文档中心入门视频&#xff1a; https://space.bilibili.com/454617261/channel/series 微服务开发&#xff1a; 单体切换为微…

数据结构与算法课后题-第二章(顺序表)

第二章 01题目&#xff0c;存储相对紧凑&#xff0c;所以存储的密度大。 04题目&#xff0c;顺序表可以按照序号随机存取&#xff0c;时间的复杂度为O(1)。 第7题目分析 #include <iostream> using namespace std;#define MaxSize 50 typedef int ElemType; typedef…

算法通过村第八关-树(深度优先)白银笔记|深度和高度问题

文章目录 前言1. 最大深度问题2. 判断平衡树3. 最小深度4. N叉树的最大深度总结 前言 提示&#xff1a;我的整个生命&#xff0c;只是一场为了提升社会地位的低俗斗争。--埃莱娜费兰特《失踪的孩子》 这一关我们看一些比较特别的题目&#xff0c;关于二叉树的深度和高度问题。这…

ORA-00257:archiver error.Connect internal only,until freed.

ORA-00257:archiver error.Connect internal only,until freed. 1、报错原因 归档满了2、解决方法 1.查看归档路径 archive log list;Arcive destination USE_DB_RECOVERY_FILE_DEST此参数代表归档存放路径&#xff0c;本地存放为/opt/oracle…&#xff0c;asm为archdg …

保姆级式教程:教你制作电子画册

在这个数字化时代&#xff0c;电子画册成为了展示和分享作品的一种流行方式。制作一个精美的电子画册不仅可以展示你的创意和才华&#xff0c;还可以吸引更多人的关注和欣赏。下面告诉大家一些小步骤&#xff0c;带你一步步学习如何制作电子画册。 1.收集和整理作品 接下来&am…

ICS TRIPLEX T8151B 数字量输入模块

ICS TRIPLEX T8151B 是一种数字量输入模块&#xff0c;通常用于工业控制和自动化系统中&#xff0c;用于监测和采集数字输入信号&#xff0c;例如开关状态、传感器状态或离散信号。以下是可能包括在 ICS TRIPLEX T8151B 数字量输入模块中的一些常见产品功能&#xff1a; 数字输…

全局异常处理+JSR303验证

一、前言 我们在日常开发中&#xff0c;避不开的就是参数校验&#xff0c;有人说前端不是会在表单中进行校验的吗&#xff1f;在后端中&#xff0c;我们可以直接不管前端怎么样判断过滤&#xff0c;我们后端都需要进行再次判断&#xff0c; 为了安全 。因为前端很容易拜托&…

Chemdraw 使用小技巧

Chemdraw 快速画分子结构 Chemdraw中有个join 功能&#xff0c;可将多个分子快速的连接在一起&#xff0c;还有group以及ungroup 功能也可以快速实现。Chemdraw画布太小&#xff0c;利用page-document settings, Layout-Poster&#xff0c;修改height, widthChemdraw快速创建新…

C语言练习题解析(4)

&#x1f493;博客主页&#xff1a;江池俊的博客⏩收录专栏&#xff1a;C语言刷题专栏&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐ 文…

Flink-CDC 抽取SQLServer问题总结

Flink-CDC 抽取SQLServer问题总结 背景 flink-cdc 抽取数据到kafka 中&#xff0c;使用flink-sql进行开发&#xff0c;相关问题总结flink-cdc 配置SQLServer cdc参数 1.创建CDC 使用的角色, 并授权给其查询待采集数据数据库 -- a.创建角色 create role flink_role;-- b.授权…

el-upload 上传附件(拆解步骤)

目录 1. 看elementui /element-plus 官网案例 2. html部分&#xff1a; 把官网上的搬下来&#xff0c;最好加一个按钮&#xff0c;上传到服务器&#xff08;后端&#xff09; 3. js 部分&#xff1a; 3.1 首先&#xff0c;先定义一个变量&#xff0c;files 3.2 当上传图片…