JPA关联MyBatis

news2024/11/13 20:25:32

3.1 JPA 多表查询

       多表查询在 Spring Data JPA 中有两种实现方式,第一种是创建一个结果集的接口来接受多表连接查询后的结果,第二种是利用 JPA 的关联映射来实现

3.1.1 数据库表及关系

      CRM 数据库中除 sys_user(用户)表外,还包括sys_role(角色)表。

      sys_role(角色)表脚本:

CREATE TABLE `sys_role` (
  `role_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `role_name` varchar(50) DEFAULT NULL COMMENT '角色名称',
  `role_desc` varchar(50) DEFAULT NULL COMMENT '角色描述',
  `role_flag` int(11) DEFAULT NULL COMMENT '状态',
  PRIMARY KEY (`role_id`),
  UNIQUE KEY `role_id` (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8

        sys_user(用户)表与 sys_role(角色)表之间存在着主外键关系, sys_user(用户)表中的usr_role_id外键字段对应sys_role(角色)表中的主键 role_id 字段。

3.1.2 多表联接查询

        1.在 com.bdqn.crm.entity 包下创建Role实体类

@Entity
@Table(name = "sys_role")
public class Role implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "role_id")
  private long roleId;
  @Column(name = "role_name")
  private String roleName;
  @Column(name = "role_desc")
  private String roleDesc;
  @Column(name = "role_flag")
  private long roleFlag;

2.在 com.bdqn.crm.vo 包下创建 UserInfo 接口,里面提供所需数据的getter方法,其中包括用户数据和角色名称(roleName)。

public interface UserInfo {
    Long getUsrId();
    String getUsrName();
    String getUsrPassword();
    Long getUsrRoleId();
    Integer getUsrFlag();
    // 角色名称
    String getRoleName();
}
  • 在运行中Spring会给接口(UserInfo)自动生产一个代理类来接收返回的结果,代码中使用getXX的形式来获取。

3.在UserRepository中添加查询方法,返回类型设置UserInfo:

@Query("select u.usrId as usrId, u.usrName as usrName, u.usrPassword as usrPassword,"
            + "u.role.roleId as usrRoleId, u.usrFlag as usrFlag, r.roleName as roleName "
            + "from User u, Role r where u.role.roleId=r.roleId and u.usrId=?1")
    public UserInfo getUserInfo(Long usrId);

4.测试验证:

@Test
    public void testGetUserInfo(){//测试多表联接查询
        UserInfo userInfo = userRepository.getUserInfo(2L);
        System.out.println("usrName:" + userInfo.getUsrName());
        System.out.println("roleName:" + userInfo.getRoleName());
    }

3.1.3 关联映射

具体例子来介绍如何映射以下关联关系:

  • 以 User 和 Role 为例,介绍如何映射多对一单项关联映射
  • 以 Role 和 User 为例,介绍如何映射一对多双向关联映射

3.1.3.1 单向多对一关联

        首先以 User 和 Role 为例,介绍通过使用外键来建立多对一的单向关联关系。

        1.修改 User 实体,添加关联 Role 对象:

@Entity
@Table(name = "sys_user")
//@NamedQueries(@NamedQuery(name = "User.findUsersByName",query = "select u from User u where u.usrName = ?1"))
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "usr_id")
    private Long usrId;
    @Column(name = "usr_name")
    private String usrName;
    @Column(name = "usr_password")
    private String usrPassword;
    @ManyToOne(targetEntity = Role.class)
    @JoinColumn(name = "usr_role_id")
    private Role role;
    @Column(name = "usr_flag")
    private Integer usrFlag;
  • @ManyToOne 注解映射多对一关联关系,targetEntity 属性表示关联实体类型,可省略;
  • @JoinColumn 注解映射关联的外键字段,如不指定,则生成一张新表维护两个对象之间的关系;

2.创建 UserRepository

public interface UserRepository extends JpaRepository<User,Long>, JpaSpecificationExecutor<User> {
}

3.测试基本的CRUD

 @Test
    public void testGet(){//测试按主键查询用户,并输出关联的用户数量
        Role role = roleRepository.findById(1L).get();
        System.out.println("roleName:" + role.getRoleName());
        System.out.println("users.size:" + role.getUsers().size());
    }

3.1.3.2 双向一对多关联

在前面的实例中,已经建立了 User 类到 Role 类的单向多对一关联,下面再继续通过示例完成Role 类到 User 类的双向一对多关联。

1.修改 Role 实体类,添加关联的 User 对象集合:

@Entity
@Table(name = "sys_role")
public class Role implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "role_id")
  private long roleId;
  @Column(name = "role_name")
  private String roleName;
  @Column(name = "role_desc")
  private String roleDesc;
  @Column(name = "role_flag")
  private long roleFlag;
  @OneToMany(targetEntity = User.class,fetch = FetchType.EAGER,cascade = CascadeType.PERSIST,mappedBy = "role")
  private Set<User> users = new HashSet<User>();
  // 省略其他代码
}
  • targetEntity 属性表示关联的实体类
  • fetch 属性表示加载策略,FetchType 取值有LAZY 及 EAGER ,LAZY 表示延迟加载,EAGER 表示立即加载,@ManyToOne 注解也包含该属性,且默认值为EAGER,表示立即加载,所以查询 User 时通过左外连接立即获取Role 数据;@OneToMany 注解表示该属性默认值为 LAZY。
  • cascade 属性表示级联操作,CascadeType 取值有 PERSIST、REMOVE、ALL ......等。
  • mappedBy 属性用来设置对象之间的关系维护方

2.创建RoleRepositoty

public interface RoleRepository extends JpaRepository<Role,Long> {
}

3.测试查询

@Test
    public void testGet(){//测试按主键查询用户,并输出关联的用户数量
        Role role = roleRepository.findById(1L).get();
        System.out.println("roleName:" + role.getRoleName());
        System.out.println("users.size:" + role.getUsers().size());
    }

4.测试级联操作:级联新增

 @Test
    public void testAdd(){ // 测试级联新增
        Role role = new Role("测试角色","演示级联新增角色和用户",1);
        User user1 = new User("测试角色1","123456",role,1);
        User user2 = new User("测试角色2",                                                                                                                                                                                        "123456",role,1);
        // 将 User 添加到 Role 的users 集合中,进行级联新增
        role.getUsers().add(user1);
        role.getUsers().add(user2);
        roleRepository.save((role)); // 新增角色的同时新增关联的用户
    }

5.测试级联操作:级联删除

        将级联属性的值改为REMOVE,再来测试级联删除,将刚刚创建的 Role 对象及关联的 User 对象一次删除。

@Test
    public void testDelete(){ // 测试级联删除
        // 先使用 getOne 方法获取到 Role 的应用,然后调用 delete 方法删除
        Role role = roleRepository.getOne(33L);
        userRepository.deleteByRoleId(role.getRoleId());
        roleRepository.delete(role);
    }

3.2 Spring Boot 集成 MyBaties

优点:

  • SQL 被统一提取出来,便于统一管理和优化
  • SQL 和代码解耦,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护、更易单元测试
  • 提供映射标签,支持对象与数据库的 ORM 字段关系映射
  • 提供对象关系映射标签,支持对象关系组件维护
  • 灵活书写动态 SQL,支持各种条件来动态生成不同的 SQL 

缺点:

  • 编写 SQL 语句时工作量很大,尤其是字段多、关联表多时,更是如此
  • SQL 语句依赖于数据库,导致数据库移植性差

3.2.2.2 xml 配置版集成

        XML 版本保持映射文件的方式,且最佳的开发方式不需要实现 Dao 的实现层,系统会自动根据方法名在映射文件中找到对应的SQL。

        接下来给大家介绍一下如何使用XML 配置版集成 Spring Boot。

1.创建项目:

2.添加关键依赖包:

        任何使用方式都需要首先在 pox.xml 中引入 mybatis-spring-boot-starter 的启动器,我们使用项目向导添加的依赖如下:

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.18</version>
        </dependency>

3.application.properties 配置相关信息:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///crm?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=liuyuhan

mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.bdqn.crm.pojo

5.启动类:

        在启动类中添加对Mapper包扫描@MapperScan,Spring Boot 启动的时候会自动加载包路径下的 Mapper。

@SpringBootApplication
@MapperScan("com.bdqn.crm.mapper")
public class MybatiesXmlApplication {

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

}

6.编码:

resource/mybatis 目录下添加mybatis-config.xml,配置一些全局属性:

    <!-- 全局配置文件 -->
    <settings>
        <!-- 开启二级缓存 -->
        <setting name="cacheEnabled" value="true" />
        <!-- 开启控制台日志 -->
    <!-- <setting name="logImpl" value="STDOUT_LOGGING" />-->
        <setting name="lazyLoadingEnabled" value="true" />
        <!--全自动映射级别-->
        <setting name="autoMappingBehavior" value="FULL" />
    </settings>

        编写实体类 User.java:

public class User implements Serializable {

    private long usrId;
    private String usrName;
    private String usrPassword;
    private long usrRoleId;
    private long usrFlag;
    // 省略 setter&getter
}

编写 Mapper 接口:

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

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

相关文章

触想内嵌式工业一体机应用于智能检票机改善旅游体验

一、行业发展背景 每年下半年&#xff0c;暑假、中秋、国庆总是接踵而至&#xff0c;随之而来的出游高峰一波接一波。凶猛需求之下&#xff0c;各地景区、游乐园客流压力加大&#xff0c;特别在检票环节&#xff0c;人工检票效率低、秩序混乱&#xff0c;导致常常出现检票口人山…

POL(Point-of-Load)负载点电源

负载点&#xff08;POL&#xff09;电源在靠近负载处单独放置电源调节器(线性稳压器或DC-DC)&#xff0c;解决了高性能半导体器件&#xff0c;例如&#xff1a;微控制器、ASIC等&#xff0c;所面临的高峰值电流、低噪声裕量等设计挑战。 一般我们会把负载点电源尽量靠近负载放…

乾元通多卡聚合技术在无人配送车应用领域通信保障方案

在无人驾驶公交车、安防车、售卖车、清扫车相继亮相后&#xff0c;无人配送车在全国各地也陆续“上岗”&#xff0c;为我们的城市带来了与众不同的“智慧体验”&#xff0c;让城市有了“科技温度”。 无人配送车在营业部装载好快递后&#xff0c;会按照提前规划好的路线出发&a…

sqli-labs靶场通关攻略 61-65

主页有sqli-labs靶场通关攻略 1-60 第六一关 less-61 步骤一&#xff1a;闭合方式&#xff1a;?id1)) -- 步骤二&#xff1a;查询数据库 ?id1)) and updatexml(1,concat(1,database()),1) -- 步骤三&#xff1a;查出网站的数据库表名 ?id1)) and updatexml(1,concat(0x7e…

15 用户管理

如果我们只能使用root用户&#xff0c;这样存在安全隐患。这时&#xff0c;就需要使用mysql的用户管理 张三只能操纵mytest这个库&#xff0c;李四只能操纵msg这个库&#xff0c;如果给他们root账户&#xff0c;就可以操纵所有库&#xff0c;风险太大 用户 用户信息 用户都存…

项目技巧三

目录 我们现在要实现一个接口功能 1.我们先书写sql语句 2.编写接口 3.书写业务逻辑 4.书写mapper 结果&#xff1a; 缺点&#xff1a;没有根据涨跌幅区间的大小来排序 1.yml文件 2.在value object包下映射这个yml文件 3.开启这个配置类进行映射&#xff0c;并把它交给s…

勒索攻击后快速恢复的八个关键步骤,如何避免被勒索攻击

勒索软件攻击依然是当今企业面临的最大安全威胁之一。根据德迅云安全收集的报告&#xff0c;59%的企业在2023年遭遇了勒索软件攻击&#xff0c;其中56%的受害者最终选择支付赎金以恢复数据。更为严重的是&#xff0c;63%的勒索金额达到或超过了100万美元&#xff0c;平均支付金…

RS232转RS485

1.232转485转换器 232转485转换器是RS-232与RS-485之间的双向接口的转换器&#xff0c;应用于主控机之间&#xff0c;主控机与单片机或外设之间构成点到点&#xff0c;点到多点远程多机通信网络&#xff0c;实现多机应答通信&#xff0c;广泛地应用于工业自动化控制系统&#x…

免费申请aws一年免费服务器使用教程

由于近期要测试一个公网项目&#xff0c;对比之下&#xff0c;选择了aws服务器&#xff0c;免费使用一年。 准备&#xff1a;一个visa信用卡即可&#xff0c;需要一个外网邮箱&#xff08;我这边使用的hotmail&#xff09; 注册的步骤不再赘述&#xff0c;切记几个点&#xff0…

windows 环境下安装OpenCV For Java

windows 环境下安装OpenCV For Java 进入官网下载对应安装包 opencv官网地址&#xff1a; https://opencv.org/releases/ source里面是官方的xml文件&#xff0c;包含人脸识别 windows下载下来是一个exe文件&#xff0c;里面包含项目需要的jar包 执行opencv-4.9.0-windows.ex…

被低估的SQL

SQL是现代数据库管理系统中不可或缺的一部分。尽管它的使用已十分普遍&#xff0c;但在数据处理领域&#xff0c;SQL的某些功能和潜力仍然被许多人低估。接下来&#xff0c;小编将与您一起&#xff0c;探讨SQL的一些被忽视的特性&#xff0c;揭示它在数据管理中的真正实力。 1.…

《深度学习》OpenCV轮廓检测 轮廓近似、模板匹配 解析及实现

一、轮廓近似 1、什么是轮廓近似 指对轮廓进行逼近或拟合&#xff0c;得到近似的轮廓。在图像处理中&#xff0c;轮廓表示了图像中物体的边界&#xff0c;因此轮廓近似可以用来描述和识别物体的形状。 2、参数解析 1&#xff09;用法 import cv2 approx cv2.approxPolyDP(cu…

Java SpringBoot构建助农平台,三步实现高效捐赠,2025届设计新思路!

✍✍计算机毕业编程指导师** ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java…

如何应对 Android 面试官 -> 内存如何进行优化?玩转 LeakCanary

前言 本章主要围绕内存相关的知识点讲解&#xff1b; 内存分配 在内存优化中&#xff0c;我们通常需要借助一些常用的 adb 命令&#xff0c;方便我们快速定位&#xff0c;下面是一些常用的 adb 命令总结 常用 adb 命令 adb shell getprop ro.product.model // 手机型号adb s…

HTTP“请求”和“响应”的报头及正文详解

目录 一、请求 "报头" (header) 二、请求 "正文" (body) 2.1 application/x-www-form-urlencoded 2.2 multipart/form-data 2.3 application/json 三、HTTP 响应状态码 四、响应 "报头" (header) 五、响应 "正文" (body) 5.1…

如何设置Word文档部分内容无法编辑?

工作中&#xff0c;我们可能会在word中制作一些请柬、表格之类的&#xff0c;有些文件内容不想要进行修改&#xff0c;为了防止他人随意修改内容。我们可以设置限制编辑&#xff0c;可以对一部分内容设置限制编辑&#xff0c;具体方法如下&#xff1a; 我们将需要将可以编辑的…

记录 PyQt6 / PySide 6 自定义边框窗口的 Bug 及可能可行的解决方案:窗口抖动和添加 DWM 环绕阴影的大致原理

前言&#xff1a; 本篇文章将要讨论我在前不久发表的关于 PyQt6 / PySide6 自定义边框窗口代码及内容中的问题&#xff1a; &#xff08;终&#xff09;PyQt6 / PySide 6 Pywin32 自定义标题栏窗口 完全还原 Windows 原生窗口边框特效_pyside6 win32 无边框窗口-CSDN博客ht…

【C++11(一)之入门基础)】

文章目录 C简介统一的列表初始化&#xff5b;&#xff5d;初始化 std::initializer_liststd::initializer_list是什么类型&#xff1a;std::initializer_list使用场景&#xff1a; 声明autodecltypenullptr STL中一些变化 C简介 在2003年C标准委员会曾经提交了一份技术勘误表(…

报告 | 以消费者为中心,消费品零售行业数字化建设持续深化

​2024年是“消费促进年”&#xff0c;国内消费市场稳步复苏。在消费需求多样化、国家政策的推动下&#xff0c;“数字化转型”仍是消费品零售行业的年度主题词&#xff0c;是品牌方获取核心竞争力的必要途径。消费品零售行业的数字化转型重心有所调整&#xff0c;从线上渠道布…

ARM架构

一、内存分布结构 栈&#xff1a;局部变量 函数参数 函数返回地址 堆&#xff1a;程序员自己管理的内存区域&#xff0c;使用是需要动态申请&#xff0c;使用捷顺后需要释放 bss&#xff1a; 初始化为0和未初始化的全局及静态变量 data&#xff1a;初始化不为0全局及静态变量…