MyBatis复习笔记

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子标签进行关联多方Order2.属性:1)property="orders" 这里的orders表示User类的成员变量orders2)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">SELECTtbo.id as oid,tbo.order_number,tbu.id as uid,tbu.user_name,tbu.password,tbu.name,tbu.age,tbu.sexFROMtb_user tbuINNER JOIN tb_order tbo ON tbu.id = tbo.user_idWHEREtbu.id = #{id}</select>

总结下:

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

4.3 多对多查询

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

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

# 【需求】:查询订单号为20140921001的订单的详情信息 订单的详情信息 = 订单+商品
SELECT*
FROMtb_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">SELECTtbo.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_priceFROMtb_order tboINNER JOIN tb_orderdetail detail ON tbo.id = detail.order_idINNER JOIN tb_item item ON detail.item_id = item.idWHEREtbo.order_number = #{orderNumber};</select>

4.4 高级查询总结

resutlType无法帮助我们自动的去完成映射,所以只有使用resultMap手动的进行映射
resultMap: 属性:type 结果集对应的数据类型  Orderid 唯一标识,被引用的时候,进行指定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.mzph.cn/bicheng/17158.shtml

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

相关文章

如何去除视频上的文字?免费无痕去水印分享!视频制作良器!

对于需要进行二次创作的视频素材&#xff0c;去除原有的文字可以提供一个更加干净的画布&#xff0c;方便创作者在其基础上进行新的创作和编辑。同时&#xff0c;去除文字后的视频也更方便分享到各种平台&#xff0c;避免因为平台对文字的限制而导致视频无法发布或传播。 要去除…

云计算期末复习(1)

云计算基础 作业&#xff08;问答题&#xff09; &#xff08;1&#xff09;总结云计算的特点。 透明的云端计算服务 “无限”多的计算资源&#xff0c;提供强大的计算能力 按需分配&#xff0c;弹性伸缩&#xff0c;取用方便&#xff0c;成本低廉资源共享&#xff0c;降低企…

Windows操作系统基本知识整理

目录 引言 一、Windows操作系统的发展历史 1.1 Windows 1.0到Windows 3.0 1.2 Windows 95到Windows Me 1.3 Windows NT到Windows 2000 1.4 Windows XP到Windows 7 1.5 Windows 8到Windows 10 二、Windows操作系统的核心组件 2.1 内核 2.2 文件系统 2.3 图形用户界面&…

内网横向移动小补充 --->PTK

大家别急&#xff0c;我的基于资源的约束性委派攻击还在写&#xff0c;这个东西一时半会讲不清楚&#xff0c;所以我在这里先来补充一点横向移动以前没说好的东西&#xff01;&#xff01;&#xff01; 在更啦&#xff0c;别催啦~~~~ 还记得我之前在内网渗透里面讲过这个PTK&a…

亚马逊云主管马特·加尔曼面临压力,致力于在人工智能领域赶超竞争对手

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

mysql中连接查询的成本

大家好。上篇文章我们讲了mysql中成本的含义以及单表查询如何计算成本。现在我们接着讲讲mysql中连接查询的成本。 在讲之前&#xff0c;我们先创建两张一样的表single_table和single_table2&#xff0c;并在表中插入10000条数据。在下面的讲解中&#xff0c;我们称single_tab…

java并发工具类都有哪些

Java中的并发工具类包括&#xff1a; CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成某些操作。它通常用于线程间的同步&#xff0c;例如在一个线程完成其工作后通知其他线程继续执行。 CyclicBarrier CyclicBarrier是一个同步辅助类&#xff0c;它允许一…

【面试必看】Java并发

并发 1. 线程 1. 线程vs进程 进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。 系统运行一个程序即是一个进程从创建&#xff0c;运行到消亡的过程。在 Java 中&#xff0c;当我们启动 main 函数时其实就是启动了一个 JVM 的进…

ChaosMeta V0.7.0 版本发布 进入CNCF混沌工程全景图

混沌工程 ChaosMeta 的全新版本 V0.7.0 现已正式发布&#xff01;该版本包含了许多新特性和增强功能&#xff0c;在编排界面提供了多集群管理&#xff0c;在代码层面支持多命令下发通道的选择。另外由蚂蚁集团发起的ChaosMeta于北京时间2024年1月10日正式进入CNCF混沌工程全景图…

07_Servlet

Servlet 一 Servlet简介 1.1 动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运行之前就写好的资源. 例如:html css js img ,音频文件和视频文件 动态资源 需要在程序运行时通过代码运行生成的资源,在程序运行之前无法确定的数据,运行时动态生成…

转行一年了

关注、星标公众号&#xff0c;直达精彩内容 ID&#xff1a;技术让梦想更伟大 整理&#xff1a;李肖遥 来公司一年了。 说是转行其实还是在半导体行业&#xff0c;熟悉我的朋友知道 &#xff0c;我在18年开始进入半导体行业&#xff0c;那个时候想着行业很重要&#xff0c;站对了…

气泡水位计的安装方法详解(二)

气泡水位计的安装方法详解&#xff08;二&#xff09; 产品简介 气泡式水位计ZL-BWL-013是一款适用于水文、水利信息化建设领域的新一代水位测量类设备&#xff0c;产品执行GB/T 11828.2-2022标准。ZL-BWL-013气泡水位计&#xff0c;具有安装方便、易于操作&#xff0c;高精度…

算法刷题day54:搜索(一)

目录 引言一、池塘计数二、城堡问题三、山峰和山谷四、迷宫问题五、武士风度的牛六、抓住那头牛七、矩阵距离八、魔板 引言 针对于蓝桥杯&#xff0c;搜索问题还是非常之重要的&#xff0c;在省赛前深知暴搜的重要性&#xff0c;所以提前先把提高课的搜索一章给看了&#xff0…

分布式锁的原理和实现(Go)

文章目录 为什么需要分布式锁&#xff1f;go语言分布式锁的实现Redis自己的实现红锁是什么别人的带红锁的实现 etcdzk的实现 为什么需要分布式锁&#xff1f; 保证分布式系统并发请求或不同服务实例操作共享资源的安全性&#xff0c;通过一种协调机制来保证在同一时刻只有一个…

设计模式17——模板方法模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 模板方法模式&#xff08;Temp…

阿里云Linux 3.2104 LTS 64位安装SVN服务器

直接按步骤 yum install subversion 写y就行 主要是看看安装了那些文件 rpm -ql subversion 主要是为了创建版本库而准备&#xff0c;这个能一遍创建就一遍创建&#xff0c;不行就逐个创建。能创就忽略下面两个mkdir步骤。 mkdir /home/svn/groupRepos 根据新建目录作为版本…

LeetCode第131场双周赛C++题解

3158.求出出现两次数字的XOR值 给你一个数组 nums &#xff0c;数组中的数字 要么 出现一次&#xff0c;要么 出现两次。 请你返回数组中所有出现两次数字的按位 XOR 值&#xff0c;如果没有数字出现过两次&#xff0c;返回 0 。 示例 1&#xff1a; 输入&#xff1a;nums …

业务实战————Uibot6.0 .1多页面商品信息抓取RPA机器人

前言 【案例描述】 鲜果记水果店计划在淘宝电商平台上开设一家新店&#xff0c;小微是该企业运营部分的运营专员&#xff0c;主要负责公司商品上架和管理的工作。 公司计划在开店的新品促销活动中增加水果品类红富士苹果。小微需在商品上架前了解目前平台中销量前列的红富士苹…

数字水印 | 离散余弦变换 DCT 基本原理及 Python 代码实现

目录 1 基本原理2 代码实现3 图像压缩 1 基本原理 参考博客&#xff1a;https://www.cnblogs.com/zxporz/p/16072580.html D C T \mathsf{DCT} DCT 全称为 D i s c r e t e C o s i n e T r a n s f o r m \mathsf{Discrete\ Cosine\ Transform} Discrete Cosine Transfo…

新购入的读码器该如何测试呢?

物联网技术的飞速发展&#xff0c;条码二维码作为一种高效、便捷的数据传输方式&#xff0c;已经广泛应用于仓储、物流配送、零售与结算、MES系统等生活和工业领域。新购的条码二维码读码器&#xff0c;在使用前要了解它的使用方法和性能&#xff0c;以确保其性能稳定、读取准确…