0%

MyBatis

Mybatis入门
不使用代理时:
1.config.xml文件可随意放,可在resources文件下再创建文件。SqlSessionFactoryBuilder加载时路径传相对resources根目录。
2.config.xml文件中配置的mapper文件位置<mapper resource="xxx/xxx"/>可以随意放,路径相对于resources根目录下,而不是相对config.xml文件位置
3.mapper.xml文件中的命名空间(namespace=”user”)随便定义,如简单定义为数据库名即可
4.使用sqlSession.selectxxx或updatexxx等("${3中mapper文件中定义namespace}.${mapper文件中sql语句的id}")来查询

使用Mapper代理

MyBatis 配置中标签存在一定顺序,可以利用别名标签给pojo类统一省略包名,别名大小写忽略如

1
2
3
4
5

<typeAlias>
<package name="xxxx.pojo路径"/>
</typeAlias>

MyBatis标签顺序

mapper标签细节

占位符,特殊字符及parameterType省略

特殊字符如 <在xml文件 mapper标签中会被认为是标签的开始,所以在mapper标签sql中需转义(html encode)或cddata注释(
特殊字符较多时用cddata较少时用转义)如:

1
2
1 ... where xxx &lt; 10
2 ... where xxx <![CDATA[<]]>

mapper标签细节

多条件查询参数格式

  1. 不封装每个参数前加@Param注解
  2. 封装成对象
  3. 分装成Map
1
2
3
4
5
6
7
8
9
10
11
//不封装直接传
fun selectMultiParams(@Param("userName") name: String, @Param("password") password: String): List<User>

//多参数传参, 封装成User对象
fun selectMultiParams(user: User): List<User>

//多参数传参, 使用Map
fun selectMultiParams(map: Map<String, *>): List<User>

//mapper.xml
SELECT * FROM tb_use WHERE username like #{ userName } and password like #{ password }
多条件查询优化

1.以上多条件查询时,可能存在后面参数password
不传参问题,那整个SQL就会变为SELECT * FROM tb_use WHERE username like #{userName} and password like ,查询就会出错,
可以用标签优化为

1
2
3
4
5
6
7
SELECT * FROM tb_use WHERE
<if test="userName!=null and userName!='' ">
username like #{userName}
</if>
<if test="password!=null and password!=''">
and password like #{password}
</if>

2.此时如果出现第一个参数username不传仍然有问题,此时可以将所有条件都加上and开头然后
2.1 以一个恒等式 eg: where 1=1 <if test="userName!=null and userName!='' "> and username like #{userName}</if> 来避免
2.2 使用Mybatis的<where>标签实现2.1功能
<where> 1=1 <if test="userName!=null and userName!='' "> and username like #{userName}</if> <if>...</if></where>

动态单条件查询

choose (when,otherwise)选择类似switch

1
2
3
4
5
6
7
8
9
10
11
12
13
14

<select id="selectChooseParams" resultType="user">
SELECT *
FROM tb_use
where
<choose>
<when test="userName!=null and userName!='' ">
username like #{userName} <!--可以加and,<where>标签会动态去除-->
</when>
<when test="password!=null and password!=''">
password like #{password}
</when>
</choose>
</select>

同理以上语句当所有条件都不成立时会变成SELECT * FROM tb_use where,会出问题,解决方案

  1. 利用添加恒等式,让sql完成eg: <when text="..">...</when> <otherwise>1=1</otherwise>
  2. 利用标签

标签小结

1.动态删除sql中and。当sql中第一个标签语句含and时,会动态删除。但做不到动态添加and,如第2个标签缺and,不会自动添加
2.动态删除where,当标签内所有条件都不成立时,不会给语句添加where,使sql出问题.

insert值

  • 默认情况下Mybatis开始事务,故增删改时
    1.要么在创建session时factory.openSession(true)设置默认自动提交
    or
    2.在每次操作后session.commit
  • 可在插入后返回指定列数据
    <insert id="add" useGeneratedKeys="true" keyProperty="自动生成主键名">

update

可以通过标签避免,sql语法后的,问题eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<update id="update">
UPDATE tb_use
<set>
<if test="userName!=null and userName!=''">
username = #{userName},
</if>
<if test="password!=null and password!=''">
password = #{password}
</if>
<if test="age>0">
age = #{age}
</if>
</set>
WHERE id = #{id}
</update>

delete

1
fun deleteSome(@Param("ids") ids:List<Int>)
1
2
3
4
5
6
7
8
<delete id="deleteSome">
DELETE FROM tb_use WHERE id in
<!-- ids需要在接口中通过@Param("ids")手动指定,
否者collection参数类型,mybatis有自己定义key的规则,如list的key就是list,数组的key是array,而不是参数名-->
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>

注解生成sql

eg:

1
2
3
@Delete("delete from tb_use where id=#{id}")
fun delete(id: Int): Int
//这样就不用在对应的mapper文件中增加标签

ResultMap

用于映射实体类字段名与列名关系,如果2者一样则可不映射,如果不一样默认以实体类定义字段顺序映射,可通过ResultMap设定映射关系

1
2
3
4
5
6
7
8
9
10
<mapper>
mapper xml文件中定义resultMap
...
<resultMap id="userResultMap" type="user">
<result column="second_name" property="sN"/>
<result column="age_str" property="agString"/>
</resultMap>
...
</mapper>

1: 如果SQL是写在接口的注解中,则同时使用@ResultMap("${userResultMap //mapper文件定义的resultMap id}")
2: 如果SQL是通过mapper xml标签写的,则在对应标签中eg: <select id="selectAll" resultType="user" resultMap="userResultMap">

动态SQL