SpringData进阶篇-下

news2025/2/26 9:38:07

SpringData进阶篇

  • 一:故事背景
  • 二:自定义操作
    • 2.1 JPQL和SQL
      • 2.1.1 接口内定义
      • 2.1.2 调用
      • 2.2.3 SQL 方式查询
    • 2.2 规定方法名
      • 2.2.1 普通查询规则
      • 2.2.2 修饰查询
    • 2.3 Query By Example
      • 2.3.1 Repository继承QueryByExampleExecutor
      • 2.3.2 具体使用
      • 2.3.2 ExampleMatcher类中常用的方法及其作用
    • 2.4 Specifications
  • 三:多表关联
    • 3.1 一对一
    • 3.1.1 单向一对一
    • 3.1.2 双向一对一
    • 3.2 一对多
    • 3.3 多对一
    • 3.4 多对多
  • 四:总结&提升

一:故事背景

这是我的第三遍SpringData的文章,在上一篇文章中,我们讲述了通过XML和JavaConfig两种方式配置项目,使用SpringData,在不适用Sql语句的情况下,进行了CRUD,这篇文章我们将会从两个部分继续讲述SpringData,一方面是为了满足我们复杂的业务进行的自定义操作,另一方面是为了处理表与表,属性与属性的关系,进行多表关联。此篇文章目的为让大家提升SpringData的可用性,使用其支持复杂业务。

二:自定义操作

2.1 JPQL和SQL

JPQL是一种基于对象模型的查询语言,用来在Java持久化框架执行数据库操作,这里我们直接给出对应的实例,展示如何使用JPQL进行数据操作

2.1.1 接口内定义

JPQL主要通过@Query注解来进行实现查询,其写法如下:

	@Query("from User where userName=?1")
    List<User> findUserByName(String userName);
    
    @Query("from User where userName=:userName")
    List<User> findUserByName2(@Param("userName") String userName);

上文给出了两种指定参数的方法,第一种是通过?加索引的方式,第二种是通过@Param指定参数名的方式。
如果是增删改操作,需要在生命的查询方法上添加@Modifying,告诉jpa这个一个修改语句,并且还要在业务层添加 @Transactional注解,保证操作的事务性

 @Query("update User u set u.userName=:userName where u.id=:id")
    @Modifying
    int updateUserById(@Param("id") Long id,@Param("userName") String userName);

2.1.2 调用

	@Test
    public void test(){
        List<User> name = iUserRepository2.findUserByName("郝立琢");
        for (User user : name) {
            System.out.println(user.getUserName());
        }
    }

    @Test
    @Transactional
    public void testU(){
        int i = iUserRepository2.updateUserById(1L,"郝666");
        System.out.println("更新成功了~~~"+i);
    }

这里推荐一个IDEA的插件 JPA Buddy,这个插件可以给我们提示,让我们编码更加简单

2.2.3 SQL 方式查询

通过@Query的nativeQuery属性我们可以指定使用SQL查询,使用SQL查询一定要注意SQL的正确性。不要写习惯了JPQL直接使用JPQL进行对应的编写。

@Query(value = "select * from user",nativeQuery = true)
    List<User> selectAll();

2.2 规定方法名

规定方法名是一种更加简单的方式,我们只需要在接口能按照对应的规则设置对应方法,就可以直接使用

2.2.1 普通查询规则

在这里插入图片描述

2.2.2 修饰查询

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这种方法免去了自己编写JPQL,相比较而言更加的简单。

2.3 Query By Example

Query by Example 翻译成中文的意思是 示例查询,其允许动态创建查询,并且并不需要编写包含字段名称的查询,其支持字符串类型的灵活匹配以及其他类型的精确匹配。但不支持嵌套或者分组的属性约束。
以下为具体示例:

2.3.1 Repository继承QueryByExampleExecutor

将Repository继承QueryByExampleExecutor通过继承此接口可以可以使用示例查询

public interface IUserRepository3 extends PagingAndSortingRepository<User,Long>,QueryByExampleExecutor<User> {
}

2.3.2 具体使用

具体使用的过程中主要涉及到两个部分,第一个部分是Example类,用来声明具体的示例,通过ExampleMatcher来设置具体的匹配条件。

@ContextConfiguration(classes = SpringDataJpaConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringDataTest4 {

    private static final Logger logger = Logger.getLogger(SpringDataTest4.class.getName());

    @Autowired
    private IUserRepository3 iUserRepository3;

    @Test
    public void test() {
        User user = new User();
        user.setId(1l);
        user.setUserName("郝立琢");

        //这里注意使用的是org.springframework.data.domain.Example而不是hibernate的Example
        Example<User> example = Example.of(user);
        List<User> list = (List<User>) iUserRepository3.findAll(example);
        logger.info(String.valueOf(list));

    }

    @Test
    public void test2() {
        User user = new User();
        user.setUserName("haolizhuo");

        //匹配器,设置多条件匹配
       ExampleMatcher matcher = ExampleMatcher.matching().
               //忽略id
               withIgnorePaths("id").
               //忽略大小写
               withIgnoreCase("userName");

        //这里注意使用的是org.springframework.data.domain.Example而不是hibernate的Example
        Example<User> example = Example.of(user,matcher);
        List<User> list = (List<User>) iUserRepository3.findAll(example);
        logger.info(String.valueOf(list));

    }

}

2.3.2 ExampleMatcher类中常用的方法及其作用

在这里插入图片描述

2.4 Specifications

在之前使用Query by Example只能针对字符串进行条件设置,那如果希望对所有类型支持,可以使用Specifications,下面给出其基本写法。

 @Test
    public void test() {

        //使用内部类的方式直接进行查询
        List<User> all = iUserRepository4.findAll((Specification<User>) (root, query, criteriaBuilder) -> {

            // root 可以用来获取某个列
            // query where 设置各种条件
            // criteriaBuilder 组合(order by ,where)

            Path<String> id = root.get("id");
            Path<String> userName = root.get("userName");

            //参数一,为那个字段设置条件、参数2 为条件设置的值
            Predicate equal = criteriaBuilder.equal(userName, "郝立琢");

            return equal;
        });

        logger.info(all.get(0).getUserName());

    }

此种方式主要是通过Specification接口,里面有三个重要参数第一个是root用来获取某个列、query 设置各种条件、criteriaBuilder 组合进行查询。通过Specification我们可以定义个性化查询,但是使用起来非常的复杂。

三:多表关联

3.1 一对一

定义一对一关系,可以将两张表进行关联,通过配置,无论是增删改查都可以直接通过对应的数据对象进行直接使用。其实现主要通过@OneToOne注解和它的一些属性实现。

  1. cascade属性:
    ALL:所有
    PERSIST:插入
    MERGE:修改
    REMOVE:删除
  2. fetch属性:
    EAGER:默认是EAGER立即加载
    LAZY 懒加载是用到才会进行查询
    懒加载必须要配置事务,否则查询完之后 Session对象就会释放,下面使用的时候就无法加载了
  3. orphanRemoval属性:
    关联移除(通常在修改的时候用到),一旦将关联的数据设置为null,会删除关联数据
  4. optional属性:
    默认为true,如果设置为false则限制关联的对象为null
  5. mappedBy 属性:
    将外键约束执行另一方维护,在一对一双向的时候需要进行配置
    值 = 另一方关联属性名

3.1.1 单向一对一

单向一对一指的是在一个表内,关联另外一张表,比如我们有一章Customer表还有一章Account表,在Customer设置一个外键存储Account的id。表示在Customer表内单向一对一关联Account表。

@Data
@Entity
@Table(name = "customer")
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String userName;

    private String phone;

    @OneToOne(cascade = CascadeType.PERSIST,fetch = FetchType.LAZY)
    /**
     指定外键Id
     **/
    @JoinColumn(name = "account_id")
    private Account account;

}

此示例中我们通过@OneToOne注解指定了一对一的关系,通过@JoinColumn指定了对应的Account表的id,将两张表进行了单向关联,在我们查询Customer 表的时候,就会自动将account的数据查出来

3.1.2 双向一对一

双向一对一指的时,在我们上述将的单向一对一的基础上,Account表内也专门设置一个字段存储了Customer 表的主键,这样在查询Account的数据的时候也可以同样将Customer表的数据带上来。
这里要注意,我们可以通过@OneToOne注解的mappedBy属性来指定某一方进行依赖约束即可。

@Data
@Entity
@Table(name = "account")
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String accountName;

    @OneToOne(mappedBy = "account")
    @JoinColumn(name = "customer_id")
    private Customer customer;

}

3.2 一对多

一对多的方式,我们需要在一的那一方维护多的一方的一个List类型的对象,并且通过@OneToMany指定一对多关系,通过@JoinColumn注解指定一个维护的id,这个id会存储到多的一方的表内,表示一对多的关联关系。一对多的关联关系适合用于查询使用。

    /**
     一对多的信息,默认就是懒加载。与一对一相反
     **/
    @OneToMany
    @JoinColumn(name="message_id")
    private List<Message> messageList;

比如我们新建一个Customer类,一个Message类。Customer类与Message类是一对多的关系,我们可以在Customer类中声明一个List的集合表示一对多的关系。
这里需要注意的是一对多的关系默认是懒加载,这和一对一正好相反,因为一对多的关系关联的数据往往比较多,通过懒加载的方式(注意查询使用事务注解)可以很大程度上提升效率。

3.3 多对一

多对一的方式,我们需要在多的一方,声明一个,一的一方的对象。用上述例子而言指的是在Message类内声明一个Customer类型的对象。

    /**
     多对一的关系,适合存储多条信息的时候
     **/
    @ManyToOne
    private Customer customer;

由于我们上述例子在一对多时已经维护了@JoinColumn(name=“message_id”),这里便可以不在重复指定。
多对一的关系更加适合存储多的一方的信息时使用,通过对customer进行赋值,将对应的信息进行关联。

3.4 多对多

多对多关系会产生对应的中间表,通过中间表维护多对多关系。


    /**
     多对多的关系将会产生中间表,通过中间表维护多对多关系
     **/
    @ManyToMany
    @JoinTable(
            name = "customer_role",
            joinColumns = {@JoinColumn(name = "c_id")},
            inverseJoinColumns = {@JoinColumn(name = "r_id")}
    )
    private List<Role> roles;

四:总结&提升

本文我们讲述了SpringData的多种查询方式,以及设计到多表之间如何进行关联,关联之后的数据操作。通过此篇文章,相信你已经学会了如何使用SpringData进行开发。
我们下面的文章将会分析底层原理,以及具体项目中的整合方式,大家感兴趣可以持续关注我的专栏~

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

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

相关文章

Aspose.Words功能演示:使用 C# 从 Word 文档中读取宏

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

java-不借用三方程序情况下,使用java自动工具将可执行jar转成exe

一、先新建一个javafx项目 二、配置Artifacts 点击Artifacts,会看到新建的项目会自动创建好了 如果没有的话,可以手动创建如下操作 三、配置 按下图逐一配置即可 四、builde 5、使用java的打包命令打包 PS C:\Users\xx\Downloads\cc\exeex\out\artifacts\JavaFXApp>…

web前端 --- js事件

js事件&#xff08;event&#xff09; &#xff08;js诞生就是基于事件驱动型编程&#xff09; &#xff08;1&#xff09;事件 用户通过各种行为&#xff08;按键、鼠标点击、鼠标hover......&#xff09;行为动作&#xff0c;引起相关 js 代码的执行。 事件的三元素&#x…

多篇论文入选ICASSP 2023 火山语音有效解决多类实践问题

近日由IEEE主办、被誉为世界范围内最大规模、也是最全面的信号处理及其应用方面的顶级学术会议ICASSP2023于希腊召开&#xff0c;该会议具有权威、广泛的学界以及工业界影响力&#xff0c;备受AI领域多方关注。会上火山语音多篇论文被接收并发表&#xff0c;内容涵盖众多前沿领…

springboot+vue+java企业车间工位管理系统

。本文介绍了企业级工位管理系统的开发全过程。通过分析企业级工位管理系统管理的不足&#xff0c;创建了一个计算机管理企业级工位管理系统的方案。文章介绍了企业级工位管理系统的系统分析部分&#xff0c;包括可行性分析等&#xff0c;系统设计部分主要介绍了系统功能设计和…

Vue.js 中的过滤器和计算属性

Vue.js 中的过滤器和计算属性 Vue.js 是一款流行的 JavaScript 框架&#xff0c;它提供了一种简单而灵活的方式来构建交互式 Web 应用程序。在 Vue.js 中&#xff0c;过滤器和计算属性是两个常用的概念。它们可以帮助开发者更方便地处理数据&#xff0c;提高代码的可读性和可维…

【学习日记】操作系统-入门知识-个人学习记录

我的学习笔记链接&#xff1a; MyLinuxProgramming 参考资料 CSAPP操作系统导论OSTEP √APUEhttps://stevens.netmeister.org/631软件调试王道-操作系统操作系统真象还原小林coding-图解系统https://xiaolincoding.com嵌入式软件开发笔试面试指南Linux是怎样工作的2020 南京大…

怎么才能成为一名合法的无线电爱好者?

要想成为一名合法的无线电爱好者&#xff0c;就必须要拥有属于自己的呼号及操作证书。那么具体怎么才能获得这些呢&#xff1f;下面河南宝蓝小编就为大家详细介绍下。 车载电台 一、无线电的呼号是什么&#xff1f; 呼号&#xff0c;是从事无线电操作人员或电台&#xff0c;在…

第12章 并 发

多进程与多线程本质的区别&#xff1a;每个进程都拥有自己的一整套变量&#xff0c;而线程则共享数据。 12.1 什么是线程 将执行这个任务的代码放在一个类的run方法中&#xff0c;这个类要实现Runnable接口。 Runnable接口非常简单&#xff0c;只有一个run方法&#xff1a; …

情感分析实战(中文)-数据获取

情感分析实战(中文)-数据获取 背景&#xff1a;该专栏的目的是将自己做了N个情感分析的毕业设计的一个总结版&#xff0c;不仅自己可以在这次总结中&#xff0c;把自己过往的一些经验进行归纳&#xff0c;梳理&#xff0c;巩固自己的知识从而进一步提升&#xff0c;而帮助各大…

Ubuntu20、centos7安装部署Gitlab

目录 一、简介 二、安装GitLab 1、安装准备工作 2、安装Gitlab a、安装并配置必要的依赖 b、下载Gitlab c、启动postfix邮件服务&#xff0c;设置开机自启 d、安装Gitlab e、修改gitlab配置文件&#xff08;ip和端口&#xff09; g、更新配置文件并重启 h、通过ip地址加端口进行…

国产力作:全新Excel平台,画表格搭建软件,Access用户:告别VBA

全新Excel平台&#xff0c;功能强大到离谱&#xff1f; 最近&#xff0c;发现了一款新型的软件&#xff0c;而且还是国产的&#xff0c;功能超级强大&#xff0c;用法却很简单。就是感觉非常的厉害&#xff01; 一款全新的Excel平台&#xff0c;但是却跟Excel没有任何联系&am…

webpack.config.js基础配置(五大核心属性)

在上一节webpack零基础入门中我们在安装完webpack 和 webpack-cli依赖之后&#xff0c;直接通过npx webpack ./src/main.js --modedevelopment的方式对src下的js文件进行了打包。 其中的 ./src/main.js: 指定 Webpack 从 main.js 文件开始打包&#xff0c;不但会打包 main.js&a…

A ConvNet for the 2020s

A ConvNet for the 2020s 2020年代的ConvNet https://openaccess.thecvf.com/content/CVPR2022/papers/Liu_A_ConvNet_for_the_2020s_CVPR_2022_paper.pdf Zhuang Liu 1 , 2 ∗ ^{1,2*} 1,2∗ Hanzi Mao 1 ^1 1 Chao-Yuan Wu 1 ^1 1 Christoph Feichtenhofer 1 ^1 1 Trevor Da…

mpls vpn综合实例配置案例

如图1所示&#xff1a; 1、AR4连接公司总部财务部、AR6连接分支机构财务部&#xff0c;AR4和AR6属于vpna&#xff1b; 2、 AR5连接公司总部办公、 AR7连接分支机构办公&#xff0c; AR5和 AR7属于vpnb。 公司要求通过部署BGP/MPLS IP VPN&#xff0c;实现总部和分支机构的安全互…

2023年6月DAMA-CDGA/CDGP数据治理工程师认证到这家

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

CleanMyMac X 4.13.4许可证激活码2023最新免费版

小伙伴们&#xff0c;你们好&#xff0c;今天兔八哥爱分享来聊聊cleanmymac X如何激活&#xff0c;关于cleanmymac的基本情况说明介绍的文章,网友们对这件事情都比较关注&#xff0c;那么现在就为大家来简单介绍下&#xff0c;希望对各位小伙伴们有所帮助。在不断更新的版本中&…

数字化转型的难点是什么?该如何突破?

01为什么要进行数字化转型&#xff1f; 数字化转型不仅是企业提高效率和竞争力的必经之路&#xff0c;也是市场发展趋势的体现。 提升业务效率&#xff1a;数字化转型可以采用自动化流程、数据分析和智能化技术&#xff0c;从而提高企业业务的自动化水平&#xff0c;优化流程…

TLE7244SL-ASEMI代理英飞原装汽车芯片TLE7244SL

编辑&#xff1a;ll TLE7244SL-ASEMI代理英飞原装汽车芯片TLE7244SL 型号&#xff1a;TLE7244SL 品牌&#xff1a;Infineon(英飞凌) 封装&#xff1a;SSOP-24-150mil 类型&#xff1a;电源负载开关 TLE7244SL特性 4个输入引脚&#xff0c;提供灵活的PWM配置 由专用引脚…

XML转换成JSON

说在前面 相信大家对 XML 都不会很陌生了&#xff0c;XML 被设计用来结构化、存储以及传输信息。最近在开发过程中发现&#xff0c;有一些旧接口返回的数据格式即是 XML 的格式&#xff0c;因此需要我们对返回的 XML 数据进行解析&#xff0c;转换成我们好处理的 JSON 数据结构…