Mybatis相关知识(2)

news2024/11/15 21:30:18

Mybatis相关知识

今天接着上期mybatis相关知识进行讲解,今天主要是讲解mybatis和数据库相关的映射,标签和SQL编写等。
会结合实际业务和代码进行讲解。

1 占位符和传参的相关问题
先来看两条xml的SQL。第一条SQL从id名称可知,是根据id删除数据,数据表t_address地址表,参数是Integer类型的id。第二条SQL根据年龄查询用户,参数是Integer类型的age。

<delete id="deleteById" parameterType="Integer">
        delete from t_address where id=#{id}
    </delete>
<!-- UserMapper.xml -->
<mapper namespace="com.boger.dao.UserMapper">
    <!-- 根据年龄查询用户 -->
    <select id="getUsersByAge" resultType="User">
        SELECT * FROM User WHERE age = ${age}
    </select>
</mapper>

那么来看 两者传参的区别:

#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。
Mybatis在处理#{}时,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入

单个参数,我们可以这样传递,那么是多个参数该怎么传递呢?
传递多个参数有以下几种方法:
业务需求: 根据院系Id和用户名查询用户。 都是在UserMapper.java文件中定义方法selectUser。
(1) 按照顺序进行传参

public User selectUser(String name, int deptId);  
<select id="selectUser" resultMap="UserResultMap">    
select * from user    where user_name = #{0} and dept_id = #{1}
</select>

#{}里面的数字代表传入参数的顺序。这种方法表达不直观,一旦顺序调整就容易出错。因此,不建议使用。

(2) 使用@Param注解进行传递参数

public User selectUser(@Param("userName") String name, int @Param("deptId")deptId);
<select id="selectUser" resultMap="UserResultMap">    
select * from user    where user_name = #{userName} and dept_id = #{deptId}
</select>

#{}里面的名称对应的是注解@Param括号里面修饰的名称
可以看到在参数不多的情况推荐使用。

(3) 将参数封装到map传参

public User selectUser(Map<String, Object> paramsMap);
<select id="selectUser" parameterType="java.util.Map" resultMap="UserResultMap">    
select * from user    where user_name = #{userName} and dept_id = #{deptId}
</select>

#{}里面的名称对应的是Map里面的key名称
可以看到这种方法适合传递多个参数(尤其是三个及其三个以上),同时参数能灵活传递

(4) 通过Java实体类(javaBean)传参

public User selectUser(User user);
<select id="selectUser" parameterType="com.jourwon.pojo.User"resultMap="UserResultMap">    
select * from user    where user_name = #{userName} and dept_id = #{deptId}
</select>

参数User就是java实体类,#{}里面的名称对应的是User类里面的成员属性。此方法扩展不易,但代码可读性强,推荐使用。

2 模糊匹配的SQL
推荐常使用的两种模糊查询写法。
第一种: “%”#{param}“%”
第二种: CONCAT(’%’,#{param},’%’) 使用CONCAT()函数
例如: 业务要求: 根据输入的字符串用户名查询用户。在UserMapper.java文件定义方法selectByCondition。

User selectByCondition(String queryString);

第一种写法:

<select id="selectByCondition" parameterType="String" resultType="com.boger.User">
        select * from t_user
            where queryString like "%"#{value}"%"
    </select>

第二种写法:

<select id="selectByCondition" parameterType="String" resultType="com.boger.User">
        select * from t_user
            where queryString CONCAT(’%’,#{value},’%’) 
    </select>

3 Mybatis如何获取生成的主键
在标签中使用 useGeneratedKeys 和 keyProperty 两个属性来获取自动生成的主键值
示例:

<insert id=”AddUser” usegeneratedkeys=”true”   keyproperty=”id”>  
  insert into user(name) values (#{name})  
</insert>  

当然,除了使用 useGeneratedKeys 和 keyProperty,还可以使用下面的标签。

<selectKey resultType="int" order="AFTER" keyProperty="id">
     SELECT LAST_INSERT_ID()
    </selectKey>

于是上面的写法,就变为了下面的完整的SQL.

<insert id=”AddUser” >  
  <selectKey resultType="int" order="AFTER" keyProperty="id">
     SELECT LAST_INSERT_ID()
    </selectKey>
  insert into user(name) values (#{name}) 
</insert>  

4 Mybatis的批量操作
在 MyBatis 中执行批量操作,可以使用批量插入(batchInsert)、批量更新(batchUpdate)等方法来提高数据库操作的效率。下面用一个批量插入学生到数据库作为案例。

<!-- UserMapper.xml -->
<mapper namespace="com.boger.dao.UserMapper">
    <!-- 批量插入用户 -->
    <insert id="batchInsertUsers" parameterType="java.util.List">
        INSERT INTO User (name, age) VALUES
        <foreach collection="list" item="user" separator=",">
            (#{user.name}, #{user.age})
        </foreach>
    </insert>
</mapper>

使用的是foreach标签。foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合
上述sql语句中,collection表示的是接收的集合数据,item表示的是集合中每一个元素进行迭代时的别名。separator 表示在每次进行迭代之间以什么符号作为分隔符,常用“,”;

这里collection的属性需要特别注意:
传入的是单参数且参数类型是一个List的时候,collection属性值为list
传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
传入的参数是多个的时候,就需要把它们封装成一个Map,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key。

5 当实体类中的属性名和数据库表中的字段名不一样的解决方案
(1) 通过在查询的SQL语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
(2) 通过resultMap标签来映射字段名和实体类属性名的一一对应的关系,其中,property表示实体类属性,column表示数据库列名。通常这里容易忽视主键id的映射。id映射需要单独映射。如下图:
在这里插入图片描述
6 mapper接口的原理
通常我们在建立好mapper接口(也称为Dao接口),就需要建立好对应的mapper的xml。例如,UserMapper.java或者UserDao.java。就会有对应的UserMapper.xml或者UserDao.xml。我们注意到,这个接口,没有实现类。
mapper接口的原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao(mapper)接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回

同时,也需要注意,mapper对应的xml文件,里面通常会设置命名空间(namespace)。即

<mapper namespace="com.boger.DictMapper"> </mapper>

如果没有配置命名空间,id就不能重复。但是,在实际运用中,我们都会配置命名空间,让代码更规范。此时id就能重复。举个例子,有UserMapper TeacherMapper,我们就会创建对应的UserMapper.xml和TeacherMapper.xml。里面配置命名空间,但UserMapper和TeacherMapper里面都可以有id为selectAll的方法(查询所有)。只不过一个查询所有用户,一个查询所有讲师。职责更明确。

7 Mybatis的动态SQL
动态SQL是MyBatis的强大特性之一, 基于功能强大的OGNL表达式
动态SQL主要是来解决查询条件不确定的情况,在程序运行期间,根据提交的条件动态的完成查询

mybatis常用的动态SQL标签:
if choose when otherwise foreach set where

下面通过举例来说明:
案例1:
if:用于条件判断,根据条件决定是否包含某部分SQL语句
where: 使用where标签生成WHERE子句

<!-- UserMapper.xml -->
<mapper namespace="com.boger.dao.UserMapper">
    <!-- 根据条件查询用户 -->
    <select id="getUsersByCondition" resultType="User">
        SELECT * FROM User
        <where>
            <if test="name != null">
                AND name = #{name}
            </if>
            <if test="age != null">
                AND age = #{age}
            </if>
        </where>
    </select>
</mapper>

如果name参数不为null,则在SQL语句中添加AND name = #{name}的条件;如果age参数不为null,则在SQL语句中添加AND age = #{age}的条件。这样可以根据不同的条件生成不同的SQL查询语句。

案例2:
choose、when、otherwise元素:类似于Java中的switch语句,用于根据不同的条件选择执行不同的分支

<!-- UserMapper.xml -->
<mapper namespace="com.boger.dao.UserMapper">
    <!-- 根据条件查询用户 -->
    <select id="getUsersByCondition" resultType="User">
        SELECT * FROM User
        <where>
            <choose>
                <when test="name != null">
                    AND name = #{name}
                </when>
                <when test="age != null">
                    AND age = #{age}
                </when>
                <otherwise>
                    AND status = 'active'
                </otherwise>
            </choose>
        </where>
    </select>
</mapper>

如果name参数不为null,则在SQL语句中添加AND name = #{name}的条件;如果age参数不为null,则在SQL语句中添加AND age = #{age}的条件;如果以上条件都不满足,则在SQL语句中添加AND status = 'active’的条件。

案例3:
foreach元素:用于遍历集合或数组,并将元素应用到SQL语句中 ,在上述批量插入已讲解,这里不多赘述。

案例4:
使用 set 标签可以方便地生成 UPDATE 语句中的 SET 子句,根据不同的条件动态设置更新的字段。

<mapper namespace="com.boger.dao.UserMapper">
    <!-- 更新用户信息 -->
    <update id="updateUser" parameterType="User">
        UPDATE User
        <set>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="age != null">
                age = #{age},
            </if>
        </set>
        WHERE id = #{id}
    </update>
</mapper>

如果传入的 User 对象中的 name 属性不为 null,则将 name 字段包含在 SET 子句中;如果传入的 User 对象中的 age 属性不为 null,则将 age 字段包含在 SET 子句中。

8 Mybatis执行一对一和一对多的查询
实现方式:
(1) 单独发送一个SQL去查询关联对象,赋给主对象,然后返回主对象
(2) 嵌套查询和关联映射。 (推荐使用)

首先是一对一 使用标签 association
案例如下: 假设有两个表,User 表和 Address 表,一个用户对应一个地址。

<!-- UserMapper.xml -->
<mapper namespace="com.boger.dao.UserMapper">
    <!-- 查询用户及其地址信息 -->
    <select id="getUserWithAddress" resultMap="userWithAddressResultMap"  parameterType="Integer">
        SELECT u.id, u.name, u.age, a.id AS address_id, a.city, a.street
        FROM User u
        LEFT JOIN Address a ON u.id = a.user_id
        WHERE u.id = #{userId}
    </select>

    <!-- 定义用户和地址的关联映射 -->
    <resultMap id="userWithAddressResultMap" type="User">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <association property="address" javaType="Address">
            <id property="id" column="address_id" />
            <result property="city" column="city" />
            <result property="street" column="street" />
        </association>
    </resultMap>
</mapper>

getUserWithAddress 方法通过 LEFT JOIN 连接 User 表和 Address 表,查询指定用户及其地址信息。
使用 resultMap 标签定义了 userWithAddressResultMap 结果映射,将查询结果映射到 User 对象,并通过 association标签将 Address 对象关联到 User 对象的 address 属性上。

java代码如下:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserWithAddress(1);

执行 getUserWithAddress 方法,将会查询指定 userId为1 的用户及其关联的地址信息,将结果映射到 User 对象中。

一对多使用标签collection
案例如下: 假设有两个表,User 表和 Order 表,一个用户可以有多个订单。

<!-- UserMapper.xml -->
<mapper namespace="com.boger.dao.UserMapper">
    <!-- 查询用户及其订单信息 -->
    <select id="getUserWithOrders" resultMap="userWithOrdersResultMap">
        SELECT u.id, u.name, u.age, o.id AS order_id, o.order_number, o.order_date
        FROM User u
        LEFT JOIN Orders o ON u.id = o.user_id
        WHERE u.id = #{userId}
    </select>

    <!-- 定义用户和订单的关联映射 -->
    <resultMap id="userWithOrdersResultMap" type="User">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <collection property="orders" ofType="Order">
            <id property="id" column="order_id" />
            <result property="orderNumber" column="order_number" />
            <result property="orderDate" column="order_date" />
        </collection>
    </resultMap>
</mapper>

getUserWithOrders 方法通过 LEFT JOIN 连接 User 表和 Order 表,查询指定用户及其订单信息。
使用 resultMap标签定义了 userWithOrdersResultMap 结果映射,将查询结果映射到 User 对象,并通过 collection标签将多个 Order 对象关联到 User 对象的 orders 属性上。

Java 代码如下:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserWithOrders(1);

执行 getUserWithOrders 方法,将会查询指定 userId 为1的用户及其关联的订单信息,将结果映射到 User 对象中,并通过 orders 属性获取用户的订单列表。

关于mybatis相关的SQL编写 标签大致等就差不多到此为止了。欢迎收看,下期再见。

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

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

相关文章

cookie、session、token学习笔记

一.cookie 1.什么是cookie&#xff1f; Cookie用于存储web页面的用户信息。 Cookie是一些数据&#xff0c;存储于你电脑的文本文件中。 当web服务器向浏览器发送web页面时&#xff0c;在连接关闭后&#xff0c;服务端不会记录用户的信息。 而Cookie的作用就是用于解决“如…

【unity每日一记】 三大金星之(音频Audio + 碰撞和触发+光源组件)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

Kubernetes(k8s)部署模式发展

目录 1 简介2 物理单机(~2000)2.1 主要代表 3 虚拟化&#xff1a;初期&#xff08;2001~2009&#xff09;3.1 VMware3.2 laaS 4 虚拟化&#xff1a;成熟期&#xff08;2010~至今&#xff09;4.1 OpenStack4.2 虚拟化四巨头 5 容器化:&#xff08;2013-至今&#xff09;5.1 Dock…

【从零开始学习JAVA | 第十三篇】继承

目录 前言&#xff1a; 引入&#xff1a; 继承&#xff1a; 小拓展&#xff1a; 优点&#xff1a; 成员方法的继承问题&#xff1a; 总结&#xff1a; 前言&#xff1a; 继承是面向对象三大特性之一&#xff0c;它是在封装之后我们讲解的一个重要的性质&#xff0c;继承…

【Kubernetes资源篇】DaemonSet控制器入门实战详解

文章目录 一、DaemonSet控制器理论知识1、DaemonSet控制器是什么&#xff1f;2、DaemonSet控制器工作原理3、DaemonSet典型应用场景4、DaemonSet与Deployment的区别 二、案例&#xff1a;DaemonSet控制器实战演示1、使用DaemonSet部署日志收集组件2、DaemonSet管理Pod滚动更新 …

数据库期末复习大总结 数据库课程学习资料(包含数据库全部章节的经典例题)【我的数据库期末复习】

为刚开始上大学数据库课程 提供学习方向【我的数据库期末复习】 第一章 绪论1.1 数据库系统概述 第二章 关系数据库2.1 关系的基本概念2.2 关系的完整性 关系数据库标准语言SQL3.1.1 SQL创建模式和表3.1.2 SQL修改和删除表3.2.1 SQ单表查询3.2.2 分组聚合和分组过滤3.2.3 多表联…

Matplotlib---散点图

1. 散点图 scatter函数用于绘制散点图。下面是scatter函数的语法格式&#xff1a; scatter(x, y, sNone, cNone, markerNone, cmapNone, normNone, vminNone, vmaxNone, alphaNone, linewidthsNone, edgecolorsNone, **kwargs)参数解释&#xff1a; x&#xff1a;指定散点的…

【二分查找】详细图解

目录 一.什么是二分查找法&#xff1f; 二.算法要求 三.算法思想 图解&#xff08;要找的数k的值为3&#xff09; 参考代码 一.什么是二分查找法&#xff1f; 二分查找也称折半查找&#xff08;Binary Search&#xff09;&#xff0c;它是一种效率较高的查找方法。但是&am…

GEE:DYNAMICWORLD/V1数据集介绍

作者:CSDN @ _养乐多_ 本文将介绍GOOGLE/DYNAMICWORLD/V1数据集。 在Dynamic World数据集中,每个波段代表了某个特定类别的土地覆盖概率。这些概率表示了一个像素完全被某种土地覆盖类别所覆盖的可能性,其取值范围从0到1。每个波段的名称和描述指示了对应类别的土地覆盖类…

成为CSDN创作者的第2048天,我收获了什么?

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、Spring源码系列、Netty源码系列、Kafka源码系列、JUC源码…

linux下容器 安装 操作 介绍

介绍&#xff1a; 容器是一种轻量级的虚拟化技术&#xff0c;可以将应用程序及其依赖项打包到一个独立的运行环境中&#xff0c;从而实现快速部署、可移植性和可扩展性。容器可以在不同的操作系统和云平台上运行&#xff0c;使得应用程序的部署和管理变得更加简单和高效。 安…

八大指针笔试题带你overcome指针

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《C语言》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造…

pgsql序列的使用

大家都知道pgsql和mysql不同&#xff0c;mysql字段有有自增属性&#xff0c;pgsql并没有&#xff0c;但是pgsql和oracle一样有序列&#xff0c;很多人刚接触pgsql的时候&#xff0c;并不知道序列是什么&#xff0c;怎么用&#xff0c;下面这篇文章就介绍序列&#xff0c;并且怎…

Flutter系列(十一)实现商城首页和商品详情页

基础工程&#xff1a; Flutter系列&#xff08;四&#xff09;底部导航顶部导航图文列表完整代码_摸金青年v的博客-CSDN博客 一、前言 本文用flutter实现商城首页和商品详情页&#xff0c;效果如下图&#xff1a; 二、使用的组件 MasonryGridView.count 瀑布流插件&#xff…

几何引擎 约束求解器 3D仿真物理引擎 图形引擎

几何引擎 & 约束求解器 & 3D仿真物理引擎 & 图形引擎 1 介绍技术图谱建模主流CAD/CAM/CAE/AEC所用引擎 2 几何建模引擎2.1 介绍2.2 各家实现 3 图形引擎4 几何约束求解器4.1 介绍4.2 各家实现D-Cubed DCM&#xff08;西门子&#xff09;CGM(达索&#xff09;LGS&am…

OpenGL模型控制(旋转、平移)

1.效果图 2.平移 首先做一个鼠标双击事件&#xff0c;表示平移模型对象&#xff0c;当然&#xff0c;我们需要遍历当前哪个模型对象被选中&#xff0c;才能进行该对象的平移操作。 void AXBOpemglWidget::mouseDoubleClickEvent(QMouseEvent *event) {Q_UNUSED(event);if(m_m…

团体程序设计天梯赛-练习集L1篇⑥

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

命令行编译C程序

目录 设置MSVC环境变量 C文件编译流程 编译 链接 学习起步之初&#xff0c;先用最基础的命令行工具进行学习 设置MSVC环境变量 这个是在VS2019下进行配置的&#xff0c;位置和你安装IDE的位置有关 MSVC D:\VS2019\IDE\VC\Tools\MSVC\14.29.30133WK10_INCLUDE C:\Program …

Android App安装弹窗显示流程

一、APP的安装 1、常见安装方式 系统应用和预制应用安装――开机时完成&#xff0c;没有安装界面&#xff0c;在PKMS的构造函数中完成安装 网络下载或第三方应用安装――调用PackageManager.installPackages()&#xff0c;有安装界面。 ADB工具安装――没有安装界面&#xf…

社交登陆成功回调

1. 点击跳转至第三方授权 2. 这是使用gitee作为第三方授权进行验证 3. 授权成功则跳转至 redirect_url 4. 社交登陆回调逻辑 一、根据第三方授权提供的方式获取token &#xff08;1&#xff09;发送请求获取code码&#xff08;每次发送请求&#xff0c;code码会改变&#xff…