给SQL传参
- 概述
- Mybatis会在运行过程中,把配置文件中的SQL语句里面的#{}转换为“?”占位符,发送给 数据库执行。
- 需求
- 根据账户模糊查询
- 代码实现
<select id="selectUserLikeName1" parameterType="string" resultType="user">
select *
from tb_user
where user_name like "%"#{userName}"%"
</select>
<select id="selectUserLikeName2" parameterType="string" resultType="user">
select *
from tb_user
where user_name like "%${userName}%"
</select>
总结
- #{}
- 不能直接写到字符串中
- 可以防止SQL注入漏洞
- 不可以传入表名
- ${}
- 能直接写到字符串中
- 不可以防止SQL注入漏洞
- 可以传入表名
输入映射
概述
- 输入映射,是在映射文件中通过parameterType指定输入参数的类型。从而将用户输入的内容赋值到SQL语句的占位符中。
- 简单类型 : 包含一个值
- 基本数据类型
- 包装类
- String
- 复杂类型 : 包含多个值
- javabean实体类
- 集合
- 数组
输入映射之简单类型
- 概述
- 输入一个简单类型的值
- 需求
- 根据id查询记录
- 代码实现
<select id="selectUserById1" parameterType="int" resultType="user">
select *
from tb_user
where user_id = #{userId}
</select>
<select id="selectUserById2" resultType="user">
select *
from tb_user
where user_id = #{userId}
</select>
输入映射之零散简单类型
- 概述
- 输入多个简单类型的值
- 需求
- 根据账户和密码查询记录
- 代码实现
<select id="selectUserByNameAndPwd1" resultType="user">
select *
from tb_user
where user_name = #{param1}
and user_pwd = #{param2}
</select>
<select id="selectUserByNameAndPwd2" resultType="user">
select *
from tb_user
where user_name = #{userName}
and user_pwd = #{userPwd}
</select>
User selectUserByNameAndPwd1(String userName , String userPwd) throws Exception;
User selectUserByNameAndPwd2(@Param("userName") String userName , @Param("userPwd") String userPwd) throws Exception;
输入映射之实体类型
- 概述
- Mybatis会根据#{}中传入的数据,加工成getXxx()方法,通过反射在实体类对象中调用这个 方法,从而获取到对应的数据。填充到#{}这个位置。
- 需求
<select id="selectUserByNameAndPwd3" parameterType="user" resultType="user">
select *
from tb_user
where user_name = #{userName}
and user_pwd = #{userPwd}
</select>
<select id="selectUserByNameAndPwd4" resultType="user">
select *
from tb_user
where user_name = #{userName}
and user_pwd = #{userPwd}
</select>
- 注意事项
- #{userName}应该和getUserName()方法名一致
- parameterType="user"可以省略
输入映射之Map
- 概述
- 如果要输入多个简单类型的值,同时也找不到合适的javabean来进行封装,使用零散简单类 型(@Param)又太过复杂,此时就可以使用map封装,然后进行输入映射。
- 代码实现
<select id="selectUserByMap" parameterType="map" resultType="user">
select *
from tb_user
where user_name = #{userName}
and user_pwd = #{userPwd}
</select>
<select id="selectUserByMap2" resultType="user">
select *
from tb_user
where user_name = #{userName}
and user_pwd = #{userPwd}
</select>
- 注意事项
- #{userName}和map的key一致
- parameterType="map"可以省略
输出映射
概述
- 输出映射,是在映射文件中通过resultType指定输出结果的类型。类型可以是简单类型、复 杂类型
- 简单类型 : 包含一个值
- 基本数据类型
- 包装类
- String
- 复杂类型 : 包含多个值
- javabean实体类
- 集合
- 数组
输出映射之简单类型
- 概述
- 输出一个简单类型的结果
- 需求
- 查询总记录数
- 代码实现
<select id="selectTotalCount" resultType="long">
select count(*)
from tb_user
</select>
输出映射之实体类型
代码实现
<select id="selectUserById3" resultType="user">
select user_id userId, user_name userName, user_pwd userPwd
from tb_user
where user_id = #{userId}
</select>
注意事项
- SQL中的字段名称必须和javabean实体类的setXxx方法名一致
输出映射之Map
- 概述
- 适用于SQL查询返回的各个字段综合起来并不和任何一个现有的实体类对应,没法封装到实 体类对象中。能够封装成实体类类型的,就不使用Map类型。
- map的键存储的是字段的名,map的值存储的是字段的值
- 代码实现
<select id="selectUserById4" resultType="map">
select *
from tb_user
where user_id = #{userId}
</select>
输出映射之List
- 概述
- 查询结果返回多个实体类对象,希望把多个实体类对象放在List集合中返回。此时不需要任 何特殊处理,在resultType属性中还是设置实体类类型即可。
- 代码实现
<select id="selectUserList" resultType="user">
select *
from tb_user
</select>
输出映射之ResultMap
- 概述
- 如果数据库中的字段名称(a_column)和实体类中的属性名称(aColumn)不一致,会导致输出映射不成功!
- 可以通过设置别名、mapUnderscoreToCamelCase=true、resultMap来解决。
- resultMap自定义映射规则来达到输出映射的目的
- 代码实现
<!--自定义输出映射规则-->
<resultMap id="userMap" type="user">
<id column="user_id" property="userId" javaType="Integer"></id>
<result column="user_name" property="userName" javaType="String"></result>
<result column="user_pwd" property="userPwd" javaType="String"></result>
<result column="money" property="money" javaType="Double"></result>
</resultMap>
<select id="selectUserListByResultMap" resultMap="userMap">
select *
from tb_user
</select>
注意事项
- 如果表中的字段名和类中的属性名一致,就不需要在resultMap中自定义映射规则,可以自动输出映射。
insert实现主键返回
- 概述
- 添加记录后,获取已添加的记录的自增长的主键值。
- 分类
- ①使用useGeneratedKeys属性
- ②使用selectKey标签
- ①使用useGeneratedKeys属性
<insert id="addUser1" useGeneratedKeys="true" keyColumn="user_id" keyProperty="userId">
insert into tb_user
values (null, #{userName}, #{userPwd}, #{money})
</insert>
②使用selectKey标签
动态sql
动态SQL之sql片段
- 概述
- 在开发中,SQL的拼接很常见,有很多的sql具有重复性高的特点,这时最好把重复的sql抽 取出来,作为公用的sql片段。
- 代码实现
<!--定义SQL片段-->
<sql id="queryArgs">
user_name , user_pwd
</sql>
<select id="selectUserLikeName1" parameterType="string" resultType="user">
select
/*使用SQL片段*/
<include refid="queryArgs"></include>
from tb_user
where user_name like "%"#{userName}"%"
</select>
动态SQL之if标签
- 概述
- if标签可以根据条件动态地生成SQL语句
- 需求
- 如果账户和密码都没有就查询所有用户记录;
- 如果只有账户,就根据账户查询用户记录;
- 如果只有密码,就根据密码查询用户记录;
- 如果账户和密码都有,就根据账户和密码查询用户记录。
- 代码实现
<!--存在问题,SQL语句一成不变,无法达到需求-->
<select id="selectUserListByNameAndPwd" resultType="user">
select *
from tb_user
where user_name = #{userName}
and user_pwd = #{userPwd}
</select>
<select id="selectUserListByNameAndPwd2" resultType="user">
select *
from tb_user
where 1 = 1
<if test="userName!=null and userName!=''">
and user_name = #{userName}
</if>
<if test="userPwd!=null and userPwd!=''">
and user_Pwd = #{userPwd}
</if>
</select>
存在问题
- 不够优雅~~~
动态SQL之where标签
- 概述
- where标签会自动去掉标签体内前面多余的and/or
- 代码实现
<select id="selectUserListByWhere" resultType="user">
select *
from tb_user
<where>
<if test="userName!=null and userName!=''">
and user_name = #{userName}
</if>
<if test="userPwd!=null and userPwd!=''">
and user_Pwd = #{userPwd}
</if>
</where>
</select>
动态SQL之trim标签
常用属性
属性 | 说明 |
---|---|
prefix | 如果条件成立,生成指定前缀 |
prefixOverrides | 如果条件成立,移除指定前缀 |
suffix | 如果条件成立,生成指定后缀 |
suffixOverrides | 如果条件成立,移除指定后缀 |
代码实现
<select id="selectUserListByTrim" resultType="user">
select *
from tb_user
/*
根据条件,动态地生成where关键字,动态地移除and或or,相当于where标签
*/
<trim prefix="where" prefixOverrides="and|or">
<if test="userName!=null and userName!=''">
and user_name = #{userName}
</if>
<if test="userPwd!=null and userPwd!=''">
and user_Pwd = #{userPwd}
</if>
</trim>
</select>
动态SQL之set标签
- 概述
- 动态地生成set关键字,会自动去掉标签体内后面多余的逗号
- 需求
- 根据id修改用户信息
- 代码实现
<update id="updateUserById">
update tb_user
set
<if test="userName!=null and userName!=''">
user_name = #{userName},
</if>
<if test="userPwd!=null and userPwd!=''">
user_pwd = #{userPwd},
</if>
where user_id = #{userId}
</update>
<update id="updateUserById">
update tb_user
<set>
<if test="userName!=null and userName!=''">
user_name = #{userName},
</if>
<if test="userPwd!=null and userPwd!=''">
user_pwd = #{userPwd},
</if>
</set>
where user_id = #{userId}
</update>
动态SQL之choose标签
- 概述
- 在多个分支条件中,仅执行一个,而后面的条件匹配都会被忽略
- 代码实现
<select id="selectUserListByChoose" resultType="user">
select * from tb_user
<where>
<choose>
<when test="userName!=null and userName!=''">
user_name = #{userName}
</when>
<when test="userPwd!=null and userPwd!=''">
user_pwd = #{userPwd}
</when>
</choose>
</where>
</select>
动态SQL之批量操作(foreach标签)
动态SQL之批量查询
- 需求
- 根据一组id查询多条用户记录
- 代码实现
<!--
方式一:select * from tb_user where user_id in(1,2,3)
-->
<select id="selectUserListByIds" resultType="user">
select * from tb_user
<where>
user_id in
<foreach collection="list" open="(" separator="," close=")" item="id">
#{id}
</foreach>
</where>
</select>
<!--
方式二:select * from tb_user where user_id = 1 or user_id = 2 or user_id = 3
-->
<select id="selectUserListByIds2" resultType="user">
select * from tb_user
<where>
<foreach collection="list" separator="or" item="id">
user_id = #{id}
</foreach>
</where>
</select>
动态SQL之批量添加
- 加粗样式需求
- 批量添加用户记录
- 代码实现
<insert id="addUsers">
insert into tb_user values
<foreach collection="list" separator="," item="user">
(null,#{user.userName},#{user.userPwd},#{user.money})
</foreach>
</insert>
动态SQL之批量修改
- 需求
- 批量修改用户记录
- 代码实现
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb1?allowMultiQueries=true
username=root
password=root
<update id="updateUsers">
<foreach collection="list" separator=";" item="user">
update tb_user set user_name = #{user.userName} where user_id = #{user.userId}
</foreach>
</update>
动态SQL之批量删除
collection:传递来的参数,可以是list,array(数组),还可以是map的key,可以是pojo中的属性
item:循环中的当前元素
index:当前元素的下标
open:循环的开始
close:循环的结束
separator:分隔符
<delete id="deleteByIds" parameterType="list">
delete from user where id in
<foreach collection="list" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
多表关系设计回顾
- 一对一 : 表A中的一条记录确定表B中的一条记录,表B中的一条确定表A中的一条记录
- 比如:公司和注册地址
- 一对一查询
- 一对多:表A中的一条记录确定表B中的多条记录,表B中的一条记录确定表A中的一条记录
- 比如:部门和员工
- 一对一查询
- 一对多查询
- 多对多:表A中的一条记录确定表B中的多条记录,表B中的一条记录确定表A中的多条记录
- 比如:老师和学生
- 一对多查询