MyBatis 是持久层的一个框架,可以大大简化写SQL语句时的麻烦、使用高级映射,甚至在其他框架中深受折磨的动态SQL,也能够很方便的实现。以下是我再次阅读官网后,认为需要记录的功能,详细的介绍可以看官方文档。
一、select/insert/update/delete
-
对于select,可以支持多行插入(当然得数据库支持);
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username, password, email, bio) values <foreach item="item" collection="list" separator=","> (#{item.username}, #{item.password}, #{item.email}, #{item.bio}) </foreach> </insert>
-
对于 insert/update ,可以获取数据库生成的 key;
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio}) </insert>
-
可以使用
<sql>
定义可重用的SQL代码片段,然后在其他语句中使用 include 引入; -
参数的类型设定
- JDBC要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 JDBC 类型 (jdbcType)。
二、结果映射
-
可以设置类型别名,这样就不用输入类的全限定名。
<!-- mybatis-config.xml 中 --> <typeAlias type="com.someapp.model.User" alias="User"/> <!-- SQL 映射 XML 中 --> <select id="selectUsers" resultType="User"> select id, username, hashedPassword from some_table where id = #{id} </select>
-
解决列名和属性名不匹配:
-
方法一:
<select id="selectUsers" resultType="User"> select user_id as "id", user_name as "userName", hashed_password as "hashedPassword" from some_table where id = #{id} </select>
-
方法二:
<resultMap id="userResultMap" type="User"> <id property="id" column="user_id" /> <result property="username" column="user_name"/> <result property="password" column="hashed_password"/> </resultMap>
-
-
高级结果映射 resultMap 中有很多子元素:
- constructor:在实例化类时,注入结果到构造方法中。
- id:ID结果
- result:JavaBean 属性中普通的字段
- association:可以关联一个复杂的类型。例如:resultMap、JavaBean
- collection:一个复杂类型的集合
- discriminator:多个结果值选择一个。
-
关联的嵌套 Select 查询会导致 “N+1”查询问题,详情如,博客的表中只存了作者的Id,现在通过select语句得到作者详情信息:
<resultMap id="blogResult" type="Blog"> <association property="author" column="author_id" javaType="Author" select="selectAuthor"/> </resultMap> <select id="selectBlog" resultMap="blogResult"> SELECT * FROM BLOG WHERE ID = #{id} </select> <select id="selectAuthor" resultType="Author"> SELECT * FROM AUTHOR WHERE ID = #{id} </select>
“N+1”问题就是(如果数据集很大):执行了一条SQL语句来获取一个结果列表(“+1”),但是需要执行多条 select 查询语句来获取详细信息(“N”)。
-
针对上面的解决办法:嵌套结果映射。
-
从版本3.2.3开始,MyBatis有了另一种解决 N+1 问题的办法:存储过程返回多结果集(ResultSet)。
-
如何处理“有很多个”类型的关联(例如,一个博客会有很多篇文章):需要用到集合(collection)。同样,可以使用嵌套select查询,或者基于连接的嵌套结果映射。“ofType” 意为集合存储的类型。
<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
读作: “posts 是一个存储 Post 的 ArrayList 集合”。
-
鉴别器 discriminator。像是 Java 中的 switch 一样。
三、动态SQL
-
if:决定是否需要这个条件;
-
choose、when、otherwise:从多个条件从选择一个使用,有点像Java 中的 switch 、case、default。
-
trim、where、set:可以解决类似如下的问题,如果 if 中没有匹配上的,SQL语句就会错误:
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select>
where解决条件查询时的类似错误;set解决条件修改时的类似错误;trim是可以自定义实现前面两种标签。
-
foreach:对集合遍历。尤其是在构建 IN 条件查询语句时。可以对 List、Set、Map或数组对象遍历。
-
script:在带注解的mapper接口中使用动态SQL。