MyBatis复习笔记

news2024/10/6 6:42:38

3.Mybatis复习

3.1 xml配置

  • properties:加载配置文件

  • settings:设置驼峰映射

    <settings>
      <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
  • typeAliases:类型别名设置

    #这样在映射器里面的resultType属性不需要写实体类的全路径名
    <typeAliases>
        <package name="com.sh.pojo"/>
    </typeAliases>
    
  • mappers 映射器

    • 加载接口,关联映射文件

      <mappers>
          <package name="com.itheima.sh.dao"/>
      </mappers>
      

3.2 getMapper底层

  • 首先调用Proxy.newProxyInstance方法创建Mapper动态代理
  • 动态代理invoke方法里会传入代理对象的方法,通过method.getName()获得方法名,接着使用Xpath解析xml从而获得id=方法名的标签表达式
  • 解析resultType属性值,通过反射技术class.forName(“resultType属性值”)获取到Class对象,通过newInstance()构造返回对象
  • 解析出sql语句,执行,并且查询结果封装到返回对象中
    在这里插入图片描述

3.3 SQL语句的CRUD

  • select

    <!--parameterType="int" 表示sql语句参数id的类型,int是Integer的别名-->
    <select id="queryById" resultType="user" parameterType="int">
        select * from user where id = #{id}
    </select>
    
  • insert

    <insert id="saveUser">
        insert into user values (null ,#{username},#{birthday},#{sex},#{address})
    </insert>
    
  • update

    <update id="updateUser">
        update user set username = #{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}
    </update>
    
  • delete

    <!--删除-->
    <delete id="deleteUser" >
        delete from user where id = #{id}
    </delete>
    

3.4 主键自增

新增一条数据成功后,将这条数据的主键封装到实体类中,并查看主键的值。

userMapper.saveUser(user);
//查看新的数据的主键值
System.out.println(user.getId());//null

使用insert标签的属性useGeneratedKeys,keyProperty,keyColumn实现:

属性说明
useGeneratedKeystrue 获取自动生成的主键,相当于select last_insert_id()
keyColumn表中主键的列名
keyProperty实体类中主键的属性名
<insert id="saveUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into user values (null ,#{username},#{birthday},#{sex},#{address})
</insert>

3.5 传入多个参数

步骤一 使用@Param注解注定名称:

//根据用户名和性别查询
User queryByUserNameAndSex(@Param("username") String userName, @Param("sex") String sex);

步骤二 在接收参数时,通过指定的名称获取参数值:

<select id="queryByUserNameAndSex" resultType="User">
     select * from user where username=#{username} and sex=#{sex}
</select>

3.6 Pojo传参

接口与xml:

void saveUser(User user);
<insert id="saveUser">
    insert into user values (null ,#{username},#{birthday},#{sex},#{address})
</insert>

底层: sql语句中 #{username}取值 -> 到pojo中调用 getUsername(){}

3.7 resultMap

resultMap标签的作用:自定义结果集,自行设置结果集的封装方式

  • 配置resultMap
id属性:resultMap标签的唯一标识,不能重复,一般是用来被引用的
type属性:结果集的封装类型
autoMapping属性:操作单表时,不配置默认为true,如果pojo对象中的属性名称和表中字段名称相同,则自动映射。
<resultMap id="userResultMap" type="User" autoMapping="true">
   <!--配置主键映射关系-->
   <id column="id" property="id"></id>
   <!--配置用户名的映射关系  column 表示数据表列  property表示pojo的属性-->
  <result column="name" property="username"></result>
</resultMap>
  • 修改select标签的statement中的resultMap

    <select id="queryById" resultMap="userResultMap">
        select * from user where id = #{id}
    </select>
    

4.动态SQL,多表查询,注解开发

4.1 基本动态SQL标签

  • if标签

    <if test="判断条件">
      满足条件执行的代码
    </if>
    
  • choose,when,otherwise标签

    choose标签:分支选择(多选一,遇到成立的条件即停止)
    	when子标签:编写条件,不管有多少个when条件,一旦其中一个条件成立,后面的when条件都不执行。
               test属性:编写ognl表达式
    	otherwise子标签:当所有条件都不满足时,才会执行该条件。
    

    可能优点乱,那来举个例子:

    <!--
            根据用户名或者住址查询所有男性用户:
                如果输入了用户名则按照用户名模糊查找,
                否则就按照住址查找,两个条件只能成立一个,
                如果都不输入就查找用户名为“孙悟空”的用户。
      -->
        <select id="queryByUserNameOrAddress" resultType="user">
            select * from user where sex='男'
            <choose>
                <when test="userName!=null and userName.trim()!=''">
                    and username like '%${userName}%'
                </when>
                <when test="address!=null and address.trim()!=''">
                    and address = #{address}
                </when>
                <otherwise>
                    and username='孙悟空'
                </otherwise>
            </choose>
        </select>
    
  • where标签

    标签作用:用于拼接多选一或者同时成立的SQL情况;

    还会根据情况,动态的去掉SQL语句中的AND或者or;

    还是举个例子吧:

    需求: 如果输入了用户名按照用户名进行查询,如果输入住址,按住址进行查询,如果两者都输入,两个条件都要成立

    假如不使用where标签,select标签应该这样:

    <select id="queryByUserNameAndAge" resultType="user">
            SELECT * FROM  user where
                <if test="userName != null and userName.trim()!=''">
                    username = #{userName}
                </if>
                <if test="address!=null and address.trim()!=''">
                    AND address = #{address}
                </if>
        </select>
    

    但是,假设用户名username是空,那么用户名的sql语句不参与条件,此时sql语句就会变为:SELECT * FROM user where AND address = #{address}

    那么可以使用where关键字:

        <select id="queryByUserNameAndAge" resultType="user">
            SELECT * FROM  user
            <where>
                <if test="userName != null and userName.trim()!=''">
                    username = #{userName}
                </if>
                <if test="address!=null and address.trim()!=''">
                    AND address = #{address}
                </if>
            </where>
        </select>
    
  • set标签

    set标签:在update语句中,可以自动添加一个set关键字,并且会将动态sql最后多余的逗号去除。

    案例:修改用户信息,如果参数user中的某个属性为null,则不修改。
    在这里插入图片描述

    因此,set解决了这个问题:

        <!--选择性地对user数据进行修改-->
       <update id="updateSelectiveUser">
            update user
            <set>
                <if test="username != null and username.trim()!=''">
                    username = #{username},
                </if>
                <if test="birthday != null">
                    birthday=#{birthday},
                </if>
                <if test="sex != null and sex.trim()!=''">
                    sex=#{sex},
                </if>
                <if test="address != null and address.trim()!=''">
                    address=#{address}
                </if>
            </set>
            where id = #{id}
        </update>
    
  • foreach标签

    主要用来遍历:

    <foreach collection="集合名或者数组名" item="元素" separator="标签分隔符" open="以什么开始" close="以什么结束">
       #{元素}
    </foreach>
    

    例子:

    按照id值是1,2,3来查询用户数据

    <!--根据多个id值查询-->
    <select id="queryByIds" resultType="user">
        SELECT * FROM  user WHERE id IN
        <foreach collection="arrIds" item="ID" separator="," open="(" close=")">
            #{ID}
        </foreach>
    </select>
    

    注意!!!在mapper接口编写传参时一定要加上@Param(“arrIds”)!!!!

4.2 一对多查询

以下例子的表关系如下:

在这里插入图片描述

假如我们要查询用户id为1的订单信息,用户(1)->订单(n),sql语句为:

select * from tb_user tbu inner join tb_order tbo on tbu.id = tbo.user_id where tbu.id=1

一个用户关联多个订单 User(List orderList) ,在User类中定义一个List集合存储多个订单Order对象。

编写XML文件:

    <!--自定义结果集-->
    <resultMap id="oneToManyResult" type="User" autoMapping="true">
        <!--User的主键-->
        <id column="uid" property="id"/>
        <!--Order关联映射-->
        <!--
            1.一对多使用collection子标签进行关联多方Order
            2.属性:
                1)property="orders" 这里的orders表示User类的成员变量orders
                2)javaType="List" 表示User类的成员变量orders存储的Order对象使用的类型,这里是List,可以不配置
                3) ofType="Order" 表示List集合中存储数据的类型 Order
        -->

        <collection property="orders" javaType="List" ofType="Order" autoMapping="true">
            <!--Order的主键-->
            <id column="oid" property="id" />
        </collection>
    </resultMap>

    <!--根据用户ID查询用户及其订单数据-->
    <select id="oneToManyQuery" resultMap="oneToManyResult">
        SELECT
            tbo.id as oid,
            tbo.order_number,
            tbu.id as uid,
            tbu.user_name,
            tbu.password,
            tbu.name,
            tbu.age,
            tbu.sex
        FROM
            tb_user tbu
            INNER JOIN tb_order tbo ON tbu.id = tbo.user_id
        WHERE
            tbu.id = #{id}
    </select>

总结下:

一对多关系配置:
1、在对象中添加映射关系;
2、编写接口方法,编写SQL;
3、编写resultMap处理数据库字段和实体类之间数据的封装;

4.3 多对多查询

举个例子:查询订单号为20140921001的订单的详情信息即查询订单信息+订单中的商品信息;

订单表(n)->订单商品中间表(1)<-商品表(m) SQL大概这样:

# 【需求】:查询订单号为20140921001的订单的详情信息 订单的详情信息 = 订单+商品
SELECT
	*
FROM
	tb_order tbo
INNER JOIN tb_orderdetail detail ON tbo.id = detail.order_id
INNER JOIN tb_item item ON detail.item_id = item.id
WHERE
tbo.order_number = '20140921001';

那具体应该怎么实现呢?

首秀按,对实体类进行修改,一个订单表中关联了多个订单详情信息,所以在订单表中添加List<Orderdetail>属性;每一条订单详情记录中都包含了一条商品信息,所以需要在Orderdetail中添加一个Item属性;

编写xml:

 <!--订单及订单详情结果集-->
    <resultMap id="orderAndDetailMap" type="Order" autoMapping="true">
        <!--tb_order表 和 Order实体类-->
        <!--订单表主键-->
        <id property="id" column="oid"/>
        <!--多个订单详情 1对多:detailList-->
        <collection property="detailList" javaType="List" ofType="Orderdetail" autoMapping="true">
            <!--tb_order_detail表  和 Orderdetail实体类-->
            <!--订单详情主键  detailId表示下面sql语句的别名-->
            <id property="id" column="detailId"/>

            <!--关联商品对象  一对一:orderdetail-Item-->
            <association property="item" javaType="Item" autoMapping="true">
                <!--tb_item表 和 Item实体类  itemId 表示下面的sql语句别名-->
                <id property="id" column="itemId"/>
            </association>
        </collection>
    </resultMap>

    <!--多对多查询-->
    <select id="queryOrderAndDetailByOrderNumber" resultMap="orderAndDetailMap">
        SELECT
            tbo.id as oid,
            tbo.order_number,
            detail.id as detailId,
            detail.total_price,
            detail.status,
            item.id as itemId,
            item.item_detail,
            item.item_name,
            item.item_price
        FROM
            tb_order tbo
            INNER JOIN tb_orderdetail detail ON tbo.id = detail.order_id
            INNER JOIN tb_item item ON detail.item_id = item.id
        WHERE
            tbo.order_number = #{orderNumber};
    </select>

4.4 高级查询总结

resutlType无法帮助我们自动的去完成映射,所以只有使用resultMap手动的进行映射
resultMap: 
	属性:
        type 结果集对应的数据类型  Order
        id 唯一标识,被引用的时候,进行指定
        autoMapping 开启自动映射
        extends 继承
	子标签:
	 id:配置id属性
	 result:配置其他属性
      association:配置一对一的映射
          property 定义对象的属性名
          javaType 属性的类型
          autoMapping 开启自动映射
      collection:配置一对多的映射
          property 定义对象的属性名
          javaType 集合的类型
          ofType 集合中的元素类型 泛型
  		  autoMapping 开启自动映射

4.5 注解开发

@Insert:保存  
         Value:sql语句(和xml的配置方式一模一样)
         
@Update:更新 
         Value:sql语句
         
@Delete: 删除
         Value:sql语句
         
@Select: 查询
         Value:sql语句
         
@Options:可选配置(主键回填)
         userGeneratedKeys:开关,值为true表示可以获取主键  相当于select last_insert_id()
         keyProperty     :对象属性
         keyColumn       : 列名

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

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

相关文章

28. 正定矩阵和最小值

文章目录 1. 概述2. 正定矩阵判定条件3. 举例 1. 概述 正定矩阵这节可以将主元&#xff0c;行列式&#xff0c;特征值&#xff0c;还有不稳定性结合起来。以前我们学的是解决方程 A x b Axb Axb 的问题&#xff0c;现在升级&#xff0c;变成 x T A x b x^TAxb xTAxb &…

html 字体设置 (web端字体设置)

windows自带的字体是有版权的&#xff0c;包括微软雅黑&#xff08;方正&#xff09;、宋体&#xff08;中易&#xff09;、黑体&#xff08;中易&#xff09;等 版权算是个大坑&#xff0c;所谓为了避免版权问题&#xff0c;全部使用开源字体即可 我这里选择的是思源宋体&…

Java进阶学习笔记10——子类构造器

子类构造器的特点&#xff1a; 子类的全部构造器&#xff0c;都会先调用父类的构造器&#xff0c;再执行自己。 子类会继承父类的数据&#xff0c;可能还会使用父类的数据。所以&#xff0c;子类初始化之前&#xff0c;一定先要完成父类数据的初始化&#xff0c;原因在于&…

【pyspark速成专家】7_SparkSQL编程1

目录 一&#xff0c;RDD&#xff0c;DataFrame和DataSet对比 二&#xff0c;创建DataFrame 本节将介绍SparkSQL编程基本概念和基本用法。 不同于RDD编程的命令式编程范式&#xff0c;SparkSQL编程是一种声明式编程范式&#xff0c;我们可以通过SQL语句或者调用DataFrame的相…

2024Spring> HNU-计算机系统-实验4-Buflab-导引+验收

前言 称不上导引了&#xff0c;因为验收已经结束了。主要是最近比较忙&#xff0c;在准备期末考试。周五晚上才开始看实验&#xff0c;自己跟着做了一遍实验&#xff0c;感觉难度还是比bomblab要低的&#xff0c;但是如果用心做的话对于栈帧的理解确实能上几个档次。 实验参考…

ClickHouse 24.4 版本发布说明

本文字数&#xff1a;13148&#xff1b;估计阅读时间&#xff1a;33 分钟 审校&#xff1a;庄晓东&#xff08;魏庄&#xff09; 本文在公众号【ClickHouseInc】首发 新的一个月意味着新版本的发布&#xff01; 发布概要 本次ClickHouse 24.4版本包含了13个新功能&#x1f381;…

List Control控件绑定变量

创建基于对话框的mfc项目 添加 List Control控件 右击控件&#xff0c;选择“添加变量” 在初始化对话框代码中增加一些代码 BOOL CMFCApplication3Dlg::OnInitDialog() { //...// TODO: 在此添加额外的初始化代码DWORD dwStyle m_programLangList.GetExtendedStyle(); …

程序员的那些经典段子

哈喽&#xff0c;大家好&#xff0c;我是明智&#xff5e; 本周咱们已经解决了在面试中经常碰到的OOM问题&#xff1a; 《美团一面&#xff0c;发生OOM了&#xff0c;程序还能继续运行吗&#xff1f;》 《美团一面&#xff1a;碰到过OOM吗&#xff1f;你是怎么处理的&#xff1…

【Linux】Linux的基本指令_1

文章目录 二、基本指令1. whoami 和 who2. pwd3. ls4. clear5. mkdir 和 cd6. touch7. rmdir 和 rm 未完待续 二、基本指令 直接在命令行的末尾&#xff08;# 后面&#xff09;输入指令即可。在学习Linux指令的过程中&#xff0c;还会穿插一些关于Linux的知识点。 1. whoami …

AI助力垃圾分类开启智慧环保新时代,基于卷积神经网络模型开发实践垃圾分类识别系统

在快节奏的现代生活中&#xff0c;垃圾分类已经成为一项重要的环保举措。然而&#xff0c;面对日益复杂的垃圾种类和繁多的分类标准&#xff0c;许多人感到困惑和无奈。幸运的是&#xff0c;随着人工智能技术的飞速发展&#xff0c;AI深度学习模型为垃圾分类带来了革命性的变化…

人工智能 框架 paddlepaddle 飞桨 使用指南 使用例子 线性回归模型demo 详解

安装过程&使用指南&线性回归模型 使用例子 本来预想 是安装 到 conda 版本的 11.7的 但是电脑没有gpu 所以 安装过程稍有变动,下面简单讲下 conda create -n paddle_env117 python=3.9 由于想安装11.7版本 py 是3.9 所以虚拟环境名称也是 paddle_env117 activa…

嵌入式全栈开发学习笔记---C语言笔试复习大全21(编程题25~30)

目录 25、实现字符串的排序。&#xff08;输入hello world good&#xff0c;输出good hello world&#xff0c;其中字符串个数任意&#xff09; 26、输入两个有序的字符串&#xff08;从小到大&#xff09;&#xff0c;合并成一个有序的字符串。&#xff08;输入cdhxyz fjln …

利用EAS自动生成数据模型和sql脚本

EAS适用于敏捷开发中小系统,这节主要讲解EAS对应的模型和数据库脚本输出应用。 在这个应用程序中,用户可自定义实体模型和枚举模型,只要选择相应的实体或者枚举进行右击添加即可。 解决方案参数设定,在解决方案的设定中可设置项目名称、通用语言,命名空间和输出位置。 连…

Python+Flask+Pandas怎样实现任意时间范围的对比数据报表

话不多说,有图有源码: 1.上图 2.因为是低代码的,只能发重要有用的代码片段了 实现思路:1)获取指定时间范围内的数据:2)df合并 #----------年份替换----------------for syear in range(int(byear),int(eyear)1):start_datestr(syear)strbdate[4:]end_datestr(syear)stredate…

2024-05-22 VS2022使用modules

点击 <C 语言编程核心突破> 快速C语言入门 VS2022使用modules 前言一、准备二、使用其一, 用VS installer 安装模块:第二个选项就是, 与你的代码一同编译std模块, 这个非常简单, 但是也有坑. 总结 前言 要解决问题: 使用VS2022开启modules. 想到的思路: 跟着官方文档整…

Linux更改系统中的root密码

Linux里面的root密码忘记了怎么办&#xff1f; 1 更改系统中的 root 密码 &#xff08;1&#xff09;键盘 CtrlAltT 快捷键打开终端。 &#xff08;2&#xff09;在终端窗口中输入以下代码&#xff1a; sudo passwd root &#xff08;3&#xff09;输入锁屏密码 &#xf…

kali下载zsteg和stegpy

1.kali下载zsteg 从 GitHub 上克隆zsteg到kali git clone https://github.com/zed-0xff/zsteg 切换目录 cd zsteg 用于安装名为 zsteg 的 Ruby Gem 包 gem install zsteg 2.kali下载stegpy 下载网站内的stegpy-master压缩包GitCode - 开发者的代码家园 并拉到kali中 切换到s…

String s1 = new String(“abc“);这句话创建了几个字符串对象?

首先&#xff0c;我们来聊聊Java中的字符串&#xff08;String&#xff09;。在Java里&#xff0c;字符串是不可变的&#xff0c;也就是说&#xff0c;一旦我们创建了一个字符串&#xff0c;它的值就不能更改了。这涉及到几个核心概念&#xff1a; 字符串常量池&#xff1a;这是…

Pytorch深度学习实践笔记5

&#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;pytorch深度学习 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就是极致重复! 视频来自【b站刘二大人】 目录 1 Linear Regress…

Java 登录错误次数限制,用户禁登1小时

手机号验证码登录&#xff0c;验证码输入错误次数超5次封禁 Overridepublic boolean checkCaptcha(String phoneNum, String captcha) {String codeNum (String) redisTemplate.opsForValue().get(UserCacheNames.USER_CAPTCHA phoneNum);if (codeNum null) {throw new Wan…