MyBatis中映射文件中数据库的操作
说明: *.src/mapper/*中所有接口对应的*.xml文件(快捷方式:1.Database连接MySQL并借助Mybatis datasource插件生成)
作用:通过实现com.lycl.ssmdemo.mapper.*Mapper.java接口中的方法,进行相应的数据库操作。
[1]多表关联
①一对多:对集合属性进行封装
<!--一对多 对集合属性进行封装 ofType不能省略-->
<collection property="questions" ofType="com.wanmait.demo.pojo.Question">
<id column="question_id" jdbcType="INTEGER" property="id" />
<result column="question_title" jdbcType="VARCHAR" property="title" />
</collection>
②多对一:对实体类中包含的实体类进行封装
<!--多对一 对实体类中包含的实体类进行封装 javaType可以省略-->
<association property="questionType" javaType="com.wanmait.demo.pojo.QuestionType">
<id column="question_type_id" jdbcType="INTEGER" property="id" />
<result column="question_type_title" jdbcType="VARCHAR" property="title" />
</association>
[2]传参方式
①传参param/arg
<select id="selectPage" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from question_type
where question_type.enable=1
order by question_type.sort desc
limit #{param1},#{param2}
limit #{arg1},#{arg2}
</select>
②在Mapper接口中加@Param(“名称”)注解
1.当Mapper接口中的参数为普通参数时(如Integer/String等),可以用自定义名称,也可以用param1,param2...(按照顺序)
//Mapper接口中
List<QuestionType> selectPage(@Param("offset") Integer offset,@Param("pageSize") Integer pageSize);
<!--mapping中的Mapper.xml中-->
<select id="selectPage" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from question_type
where question_type.enable=1
order by question_type.sort desc
limit #{offset},#{pageSize}
<!--注意:也可以用param,也能混用,但是一般不这么用
limit #{param1},#{param2}-->
</select>
2.当Mapper接口中的参数为单个实体对象时(如new的Userinfo/Question 等),xml中要以“名称.属性名”
//Mapper接口中
int insert(@Param("question") QuestionType record);
<!--mapping中的Mapper.xml中-->
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.wanmait.demo.pojo.QuestionType" useGeneratedKeys="true">
insert into question_type (title,sort)
values (#{question.title,jdbcType=VARCHAR}, #{sort,jdbcType=INTEGER})
</insert>
3.当Mapper接口中的参数既有普通参数,又有实体对象时,要对所有的参数自定义名称,在xml中调用时,对象以“名称.属性名”,普通参数以“名称”即可。
[3]动态sql
拓展:
(1)trim的用法:
作用:
属性:prefix 最前缀有谁
suffix 最后缀有谁
prefixOverrides 前缀省略谁
suffixOverrides 后缀省略谁
(2)concat的用法:
作用:拼接字符串,数据之间用逗号隔开
1.多条件查询:(在多条件查询时,写where条件时,前缀可能会出现多and或者or,需要去掉多余的and/or)
方法:
(1)
(2)用
(3)在初始条件添加 1=1 这样就能保证剩余的条件开头可以接and/or
<select id="search" resultMap="BaseResultMap" parameterType="com.wanmait.demo.pojo.QuestionType">
select <include refid="Base_Column_List"></include>
from question_type
/*where 1=1*/
/*直接这样写可能会造成多一个and,
方法一:
可以在where后加一个1=1
方法二:
直接写在<where></where>标签中,可以去掉多余的and/or
*/
<!--<trim prefix="where" prefixOverrides="and|or">-->
<where>
<if test="title != null and title != ''">
/*concat拼接字符串,数据之间用逗号隔开*/
and title like concat('%',#{title} ,'%')
</if>
<if test="questionCount != null">
and question_count=#{questionCount}
</if>
<if test="sort != null">
and sort=#{sort}
</if>
<if test="enable != null">
and enable=#{enable}
</if>
</where>
<!--</trim>-->
</select>
2.多条件修改:(在多条件修改时,写set条件时,后缀可能会出现多逗号,需要去掉多余的逗号)
方法:
(1)
(2)用
<update id="update">
update question_type
<!--<trim>可以代替<set>和<where>
prefix 最前缀有谁
suffix 最后缀有谁
prefixOverrides 前缀省略谁
suffixOverrides 后缀省略谁
-->
<trim prefix="set" suffixOverrides=",">
<if test="title != null">
title=#{title},
</if>
<if test="questionCount != null">
question_count=#{questionCount},
</if>
<if test="sort != null">
sort=#{sort}
</if>
where id = #{id}
<!-- </set>-->
</trim>
</update>
3.多条件增加:(在多条件增加时,写检索列和values条件时,后缀可能会出现多逗号,以及不确定是否何处添加括号)
方法:
(1)检索列:
values:
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.wanmait.demo.pojo.QuestionType"
useGeneratedKeys="true">
insert into question_type
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="title != null">
title,
</if>
<if test="questionCount != null">
question_count,
</if>
<if test="sort != null">
sort,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="title != null">
#{title,jdbcType=VARCHAR},
</if>
<if test="questionCount != null">
#{questionCount,jdbcType=INTEGER},
</if>
<if test="sort != null">
#{sort,jdbcType=INTEGER},
</if>
</trim>
</insert>
[4]批量操作中数据的循环
方法:
(1)运行${ids}拼接实现批量操作,不需要循环:
将QuestionTypeServiceImpl中ids字符串传入deleteBatch方法中形参列表中,xml中对ids进行拼接操作
实现效果:“update question_type set enable = 0 where id in (” + ids + “)”
即:update question_type set enable = 0 where id in (1,25,3,6)
<delete id="deleteBatch">
update question_type set enable = 0 where id in (${ids})
</delete>
(2)运用
首先,QuestionTypeServiceImpl中将数据放入List集合/Integer[]数组中:
在xml中对list数据进行循环:
foreach属性:
collection:循环数组的类型
open:开始添加内容
close:结束添加内容
separator:每个数据间添加内容
item:循环的单个数据的名称
index:索引号的名称(一般没啥用)
实现效果:update question_type set enable = 0 where id (?,?,?)
方法一:List集合:
QuestionTypeMapper.xml
<delete id="deleteBatch1">
update question_type set enable = 0 where id
in
<foreach collection="list" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
QuestionTypeServiceImpl:
@Override
public void delete1(String ids) {
String[] idStrArr = ids.split(",");
List<Integer> idList = new ArrayList<>();
for (String idStr : idStrArr) {
idList.add(Integer.parseInt(idStr));
}
questionTypeMapper.deleteBatch1(idList);
}
方法二:Integer数组:
QuestionTypeMapper.xml
<delete id="deleteBatch2">
update question_type set enable = 0 where id
in
<foreach collection="array" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
QuestionTypeServiceImpl:
@Override
public void delete2(String ids) {
String[] idStrArr = ids.split(",");
Integer[] idArr = new Integer[idStrArr.length];
for (int i = 0; i < idArr.length; i++) {
idArr[i] = Integer.parseInt(idStrArr[i]);
}
questionTypeMapper.deleteBatch2(idArr);
}
方法三:哈希HashMap:
QuestionTypeMapper接口:
void deleteBatch4(Map<String,Object> map);
QuestionTypeServiceImpl实现类:
@Override
public void delete(String ids) {
String[] idStrArr = ids.split(",");
List<Integer> idList = new ArrayList<>();
for (String idStr : idStrArr) {
idList.add(Integer.parseInt(idStr));
}
Map<String,Object> map = new HashMap<>();
map.put("idList",idList);
map.put("title","a123");
questionTypeMapper.deleteBatch4(map);
}
QuestionTypeMapper.xml:映射文件中的参数名要和业务逻辑层设置的map的键名要一致,不建议使用
<delete id="deleteBatch4">
update question_type set enable = 0 where id
in
<foreach collection="idsList" open="(" close=")" separator="," item="id">
#{id}
</foreach>
and title like concat('%',#{title},'%')
</delete>
拓展1:
当传递多个参数时,在QuestionTypeMapper中运用@Param("名称")注解,则xml中foreach中collection的值为该名称 (SpringBoot中@Param注解可以省略,sp会自动加@Param,直接用形参名即可)
QuestionTypeMapper中的接口: @Param("ids")
void deleteBatch3(@Param("ids") List<Integer> ids,@Param("title") String title);
xml中:collection="ids"或者collection="param1"
<delete id="deleteBatch3">
update question_type set enable = 0 where id
in
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
and title like concat('%',#{title},'%')
</delete>
拓展2:
相较于第一种方法(拼接),第二种方法(对问号设置值)的优点:
1.防止注入攻击
2.提高执行效率(由于使用的是连接池,所以同一条语句会被多次调用,之前写的DBHelper数据库工具类,每次用完都会关闭,并不会提高效率):
①多次执行拼接类型的数据库语句,由于传的值不一样,使得相同结构的数据库语句,由于所传的数据不一样,导致数据库每次都会对该相同结构的语句进行语法检查。{例:update question_type set enable = 0 where id in (1,25,3,6)和update question_type set enable = 0 where id in (1,2)}数据库会对每条语句进行语法检查,则很多准备工作会进行重复执行
②多次执行问号设置值的数据库语句,数据库只会对第一条语句进行检查,再调用该语句传入其他值时,则不会重复执行准备工作,提高了执行效率。
[5]xml数据库映射中的选择结构(类似switch-case/if-else,有且只能有一个条件可以执行)
结构:
......
<select id="search2" resultMap="BaseResultMap" parameterType="com.wanmait.demo.pojo.QuestionType">
select
<include refid="Base_Column_List"></include>
from question_type
<where>
<choose>
<when test="title != null and title != ''">
title like concat('%',#{title} ,'%')
</when>
<when test="questionCount != null">
question_count=#{questionCount}
</when>
<otherwise>
enable=1
</otherwise>
</choose>
</where>
</select>
[6]增删改返回自增长的id(无mybatis版详见MySql数据库.md)
1. 从数据库取值的名称:**keyColumn="id"**
2. 将数据从放到对象的名称:**keyProperty="id"**
3. 设置获取主键的开关:**useGeneratedKeys="true"**
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.wanmait.demo.pojo.Question" useGeneratedKeys="true">
insert into question (title, question_type_id, userinfo_id,
info, description, has_pic, pic)
values (#{title,jdbcType=VARCHAR}, #{questionType.id,jdbcType=INTEGER}, #{userinfo.id,jdbcType=INTEGER},
#{info,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{hasPic,jdbcType=BIT},
#{pic,jdbcType=VARCHAR})
</insert>
使用实例:订单生成时,需要立刻拿到生成订单的id,以完成后续操作。

浙公网安备 33010602011771号