Spring Data JPA使用规则和审计的学习

news2024/11/25 18:42:15

一、引入依赖

完整的pom文件如下所示:

<?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.7.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>FunlyDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>FunlyDemo</name>
    <description>FunlyDemo</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>
        <!--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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

二、application.properties配置文件

#mysql
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/funly?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456

#jpa
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

三、创建用户实体类

package com.example.funlydemo.bean;

import lombok.Data;
import lombok.ToString;

import javax.persistence.*;

/**
 * @author qx
 * @date 2023/07/19
 * @desc 用户实体类
 */
@Entity
@Table(name = "t_user")
@Data
@ToString
public class User {

    /**
     * ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
}

四、JPA规则认识

启动重新创建好数据表后,我们添加一些测试数据到user表。

关键字举例       JPQL片段
And        

findAllByNameAndAge

where user0_.name=? and user0_.age=?
Or

findAllByNameOrAge

where user0_.name=? or user0_.age=?
is,Equals

findAllByNameIs,findAllByNameEquals,

findAllByName

where user0_.name=?
Between

findAllByAgeBetween

where user0_.age between ? and ?

LessThan

findAllByAgeLessThan

where user0_.age<?

LessThanEqual

findAllByAgeLessThanEqual

where user0_.age<=?

GreaterThan

findAllByAgeGreaterThan

where user0_.age>?

GreaterThanEqual

findAllByAgeGreaterThanEqual

where user0_.age>=?

IsNull

findAllByAgeIsNull

where user0_.age is null

IsNotNull

findAllByAgeIsNotNull

where user0_.age is not null

Like

findAllByNameLike

where user0_.name like ? escape ?

NotLike

findAllByNameNotLike

where user0_.name not like ? escape ?

StartingWith

findAllByNameStartingWith

where user0_.name like ?(后置%) escape ?

EndingWith

findAllByNameEndingWith

where user0_.name like ?(前置%) escape ?

Containing

findAllByNameContaining

where user0_.name like ?(双%) escape ?

OrderBy

findAllByNameOrderByAgeDesc

where user0_.name=? order by user0_.age desc

Not

findAllByNameNot

where user0_.name<>?

In

findAllByAgeIn

where user0_.age in (? , ?)

NotIn

findAllByAgeNotIn

where user0_.age not in  (? , ?)

五、持久层方法编写

package com.example.funlydemo.repository;

import com.example.funlydemo.bean.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {

    List<User> findAllByNameAndAge(String name, Integer age);

    List<User> findAllByNameOrAge(String name, Integer age);

    List<User> findAllByNameIs(String name);

    List<User> findAllByNameEquals(String name);

    List<User> findAllByName(String name);


    List<User> findAllByAgeBetween(Integer age1, Integer age2);

    List<User> findAllByAgeLessThan(Integer age);

    List<User> findAllByAgeLessThanEqual(Integer age);

    List<User> findAllByAgeGreaterThan(Integer age);

    List<User> findAllByAgeGreaterThanEqual(Integer age);

    List<User> findAllByAgeIsNull();

    List<User> findAllByAgeIsNotNull();

    List<User> findAllByNameLike(String name);

    List<User> findAllByNameNotLike(String name);

    List<User> findAllByNameStartingWith(String name);

    List<User> findAllByNameEndingWith(String name);

    List<User> findAllByNameContaining(String name);

    List<User> findAllByNameOrderByAgeDesc(String name);

    List<User> findAllByNameNot(String name);

    List<User> findAllByAgeIn(List<Integer> ageList);

    List<User> findAllByAgeNotIn(List<Integer> ageList);
}

六、单元测试类

package com.example.funlydemo;

import com.example.funlydemo.bean.User;
import com.example.funlydemo.repository.UserRepository;
import org.assertj.core.util.Lists;
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 FunlyDemoApplicationTests {

    @Autowired
    private UserRepository userRepository;

    @Test
    void testAnd() {
        List<User> userList = userRepository.findAllByNameAndAge("aa", 11);
        System.out.println(userList);
    }

    @Test
    void testOr() {
        List<User> userList = userRepository.findAllByNameOrAge("aa", 11);
        System.out.println(userList);
    }

    @Test
    void testEquals() {
        List<User> userList = userRepository.findAllByNameIs("aa");
        System.out.println(userList);

        List<User> userList1 = userRepository.findAllByNameEquals("aa");
        System.out.println(userList1);

        List<User> userList2 = userRepository.findAllByName("aa");
        System.out.println(userList2);
    }

    @Test
    void testBetween() {
        List<User> userList = userRepository.findAllByAgeBetween(12, 13);
        System.out.println(userList);
    }

    @Test
    void testLessThan() {
        List<User> userList = userRepository.findAllByAgeLessThan(12);
        System.out.println(userList);
    }

    @Test
    void testLessThanEqual() {
        List<User> userList = userRepository.findAllByAgeLessThanEqual(12);
        System.out.println(userList);
    }

    @Test
    void testGreaterThan() {
        List<User> userList = userRepository.findAllByAgeGreaterThan(12);
        System.out.println(userList);
    }

    @Test
    void testGreaterThanEqual() {
        List<User> userList = userRepository.findAllByAgeGreaterThanEqual(12);
        System.out.println(userList);
    }

    @Test
    void testIsNull() {
        List<User> userList = userRepository.findAllByAgeIsNull();
        System.out.println(userList);
    }

    @Test
    void testIsNotNull() {
        List<User> userList = userRepository.findAllByAgeIsNotNull();
        System.out.println(userList);
    }

    @Test
    void testLike() {
        List<User> userList = userRepository.findAllByNameLike("b%");
        System.out.println(userList);
    }

    @Test
    void testNotLike() {
        List<User> userList = userRepository.findAllByNameNotLike("b%");
        System.out.println(userList);
    }

    @Test
    void testStartingWith() {
        List<User> userList = userRepository.findAllByNameStartingWith("b");
        System.out.println(userList);
    }

    @Test
    void testEndingWith() {
        List<User> userList = userRepository.findAllByNameEndingWith("x");
        System.out.println(userList);
    }

    @Test
    void testContaining() {
        List<User> userList = userRepository.findAllByNameContaining("a");
        System.out.println(userList);
    }

    @Test
    void testOrderBy() {
        List<User> userList = userRepository.findAllByNameOrderByAgeDesc("aa");
        System.out.println(userList);
    }

    @Test
    void testNot() {
        List<User> userList = userRepository.findAllByNameNot("aa");
        System.out.println(userList);
    }

    @Test
    void testIn() {
        List<User> userList = userRepository.findAllByAgeIn(Lists.newArrayList(11, 12));
        System.out.println(userList);
    }

    @Test
    void testNotIn() {
        List<User> userList = userRepository.findAllByAgeNotIn(Lists.newArrayList(11, 12));
        System.out.println(userList);
    }
}

七、自定义规则

我们可以使用JPQL和书写原生SQL的方式实现自定义的规则。JPQL最突出的特点就是以Java Bean为操作对象,遵循JPA规范屏蔽了数据库 之间的差异,使同一套代码可以用在任意数据库上;而SQL方式是以表为操作 对象的,因此可以使用某种数据库特有的功能,比如某个MySQL独有的功能, 但是切换到Oracle时就不能使用了。

JPQL使用示例代码如下:

   @Query("select u from User u where u.name=?1")
    List<User> getDataByName(String name);

原生SQL使用示例代码如下:

 @Query(value = "select * from t_user where name=?1",nativeQuery = true)
    List<User> getUserFromName(String name);
}

设置nativeQuery属性为true,说明使用原生SQL。

八、审计

业务数据的插入时间、最后更新时间、创建人及最后更新人的记录对每个 系统都很重要,但如果每次操作时都需要手动记录这些信息,就会非常枯燥且 烦琐。作为一个成熟的持久层框架,Spring Data JPA应该学会自己审计了。
1.启动类开启审计
package com.example.funlydemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
// 开启审计
@EnableJpaAuditing
public class FunlyDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(FunlyDemoApplication.class, args);
    }

}

2.把审计需要的属性封装到一个公共类

package com.example.funlydemo.bean;

import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

/**
 * @author qx
 * @date 2023/07/19
 * @desc
 */
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {

    @CreatedBy
    @Column(updatable = false)
    private String creater;

    @LastModifiedBy
    private String modifier;

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createTime;

    @LastModifiedDate
    private LocalDateTime updateTime;


}

@Column(updatable=false)将字段设置不可修改,只允许一次赋值。创建者和创建时间只需要插入一次,不需要更新。

3.用户类继承公共基类

package com.example.funlydemo.bean;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

import javax.persistence.*;

/**
 * @author qx
 * @date 2023/07/19
 * @desc 用户实体类
 */
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "t_user")
@Data
@ToString
public class User extends BaseEntity {

    /**
     * ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
}

4.创建一个获取当前操作人的接口实现类

package com.example.funlydemo.uti;

import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * @author qx
 * @date 2023/07/19
 * @desc 获取当前操作人的接口
 */
@Component
public class AuditorImpl implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        return Optional.of("admin->" + (int) (Math.random() * 10));
    }
}

5.测试审计

我们在单元测试中,测试添加用户

  @Test
    void testAddUser() {
        User user = new User();
        user.setName("qq");
        user.setAge(20);
        userRepository.save(user);
    }

执行方法后,我们查看数据表,发现自动添加上了创建者和创建时间。

 接下来我们测试修改用户的方法

  @Test
    void testUpdateUser(){
        Optional<User> optional = userRepository.findById(2L);
        User user = optional.get();
        user.setAge(22);
        userRepository.save(user);
    }

执行方法后,我们查看数据表,发现自动修改了更新时间和修改操作人。

 

 

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

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

相关文章

idea 常用快捷键总结

IDEA常用快捷键总结 很多新手小白在使用IDEA进行代码编写的时候 对快捷键很感兴趣 这里泡泡给大家总结了一些常用的快捷键 希望能帮助到你 记得要收藏下来时常观看并且练习&#xff0c;才能熟练哦~ 1. 根据psvm或者main快速生成主函数 我们可以在类中输入psvm 或者main 然后I…

数据结构day4(2023.7.18)

一、Xmind整理&#xff1a; 链表的插入和删除&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;顺序表去重 33 22 22 11 11 i jfor(int i0;i<list->len-1;i){for(int ji1;j<len;j){if(list->data[i]list->data[j]){delete_by_sub(j,list); …

springmvc @RequestMapping注解中produces以及consumes属性的含义(转载请删除括号里的内容)

http协议基础知识 首先需要了解什么叫MediaType&#xff08;媒体类型&#xff09;&#xff1f; 通俗来说&#xff0c;在http协议中&#xff0c;用来表示传输内容的格式就是MediaType&#xff0c;比如text/html&#xff0c;application/json等&#xff0c;其中text代表介质&am…

win7系统电脑怎么在桌面上悬挂工作日程安排清单显示呢?

在现代快节奏的工作环境中&#xff0c;合理安排和管理工作日程是非常重要的。而在电脑桌面上悬挂工作日程安排清单显示&#xff0c;可以让我们随时了解自己的任务和工作进度&#xff0c;提高工作效率。那么&#xff0c;如何在Win7系统电脑上实现这一功能呢&#xff1f; 今天我…

第六章内存保护单元(Cortex-M7 Processor)

目录 第六章内存保护单元 6.1关于MPU 6.2MPU功能描述 6.3MPU编程器模型 第六章内存保护单元 介绍MPU (Memory Protection Unit)。它包含以下部分: 关于第6-2页的MPU。MPU功能描述见第6-3页。MPU程序员模型在第6-4页。 6.1关于MPU MPU是内存保护的可选组件。处理器支持标准…

【算法基础:数据结构】2.3 并查集

文章目录 并查集算法原理&#xff08;重要&#xff01;⭐&#xff09; 经典例题836. 合并集合&#xff08;重要&#xff01;模板&#xff01;⭐&#xff09;837. 连通块中点的数量&#xff08;维护连通块大小的并查集&#xff09;240. 食物链&#xff08;维护额外信息的并查集&…

【Spring | 应用上下文】

应用上下文 应用上下文和资源路径构造应用上下文构造ClassPathXmlApplicationContext实例 — 快捷方式使用通配符蚂蚁式图案类路径&#xff1a;前缀 应用上下文和资源路径 本节介绍如何使用资源创建应用程序上下文&#xff0c;包括使用 XML 的快捷方式、如何使用通配符以及其…

能耗管理平台保障用电的安全

安科瑞虞佳豪 壹捌柒陆壹伍玖玖零玖叁 6月12日&#xff0c;江苏盐城射阳县某民房起火&#xff0c;消防救援人员到场后&#xff0c;立即对火势进行扑救&#xff0c;经过20多分钟的处置&#xff0c;现场明火全部被扑灭&#xff0c;据了解&#xff0c;起火原因是电线老化短路引发…

Mac下makefile使用openssl库

程序报错 ./polipo.h:208:10: fatal error: openssl/ssl.h file not found 安装和查找openssl开发库 brew install brew --prefix openssl cd /opt/homebrew/opt/openssl3 cd lib cd pkgconfig 通过makefile配置include文件和lib文件 pkg-config方式 lib文件查找&#xf…

C# 同构字符串

205 同构字符串 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符的顺序。不同字符不能映射到同一个字符…

Mysql教程(五):DQL学习

Mysql教程&#xff08;五&#xff09;&#xff1a;DQL学习 DQL Data Query Language 数据查询语言&#xff0c;用来查询数据库中表的记录 1 基本语法 DQL查询语句&#xff0c;语法结构如下&#xff1a; SELECT字段列表 FROM表名列表 WHERE条件列表 GROUP BY分组字段列表 HAVI…

工时管理为何对项目如此重要?8Manage 带你读懂!

“时间就是金钱”&#xff0c;相信作为管理者都已经听腻了这话&#xff0c;但在项目管理中确实是真理。你要知道项目工时是会直接影响到项目费用成本的&#xff0c;不论项目工作是按小时还是按固定费用计费和付款&#xff0c;在一段工时内完成的工作越多&#xff0c;说明效率就…

myAgv的slam算法学习以及动态避障下篇

引言 在之前的一篇文章中有提到购入了一台myAGV&#xff0c;以树莓派4B为控制核心的移动机器人。上篇文章中向大家介绍了myAGV如何实现建图、导航以及静态避障&#xff0c;但我们深知&#xff0c;这只是机器人自主导航能力的基础。在实际应用场景中&#xff0c;机器人需要面对复…

【个人笔记】linux命令之ls

目录 Linux中一切皆文件ls命令常用参数常用命令lscpu lspci Linux中一切皆文件 理解参考&#xff1a;为什么说&#xff1a;Linux中一切皆文件&#xff1f; ls命令 ls&#xff08;英文全拼&#xff1a; list directory contents&#xff09;命令用于显示指定工作目录下之内容…

宝塔 30分钟部署免费在线客服系统

客服系统发布以来&#xff0c;一直有朋友询问如何在宝塔面板中安装部署&#xff0c;开始我一直认为参考 Linux 版的安装教程就可以了&#xff0c;一直没有专门写宝塔环境的教程。这段时间来咨询的朋友越来越多&#xff0c;经过了解&#xff0c;我才知道宝塔面板的普及率有多高&…

什么是Spring Actuator?它有什么优势?

目录 一、什么是Spring Actuator 二、Spring Actuator的应用场景 三、Spring Actuator的优势 一、什么是Spring Actuator Spring Actuator是Spring Boot提供的一个功能强大的管理和监控工具&#xff0c;用于监控和管理Spring Boot应用程序。它可以提供对应用程序的运行时信…

java实现身份证号码校验

二代身份证为18位&#xff0c;前六位为籍贯信息&#xff0c;7至14位为生日&#xff0c;最后一位校验前17位号码是否正确 校验规则为&#xff1a;前17位每一位乘以一个固定权重并相加然后除以11得到的余数&#xff0c;判断余数是否和校验的数相等 代码实现&#xff08;支持15位…

leetcode 9 回文数

class Solution {public boolean isPalindrome(int x) {if(x < 0){return false;}int num x;int value 0;while(num > 0){value value * 10 num % 10;num num / 10;}return value x;} }

Enterprise:通过 App search 摄入数据

App Search 是 Elastic Enterprise Search 的一部分&#xff0c;Elastic Enterprise Search 是由 Elasticsearch 提供支持的内容搜索工具集合。 最初由 App Search 引入的一些功能&#xff08;例如网络爬虫&#xff09;现在可以直接通过企业搜索使用。 将这些功能与其他企业搜…

如何用DeepDiff测接口数据源变更?

开发同学最近变更了部分业务查询接口底层的数据源&#xff0c;希望测试同学能够针对这些接口进行一些回归验证&#xff0c;校验底层数据源更新前后业务查询接口返回的一致性&#xff0c;保证更新后对正常业务没有影响。 这个回归测试和一般接口测试有所区别&#xff0c;不仅仅…