Loading

MyBatis的一些使用细节



CDATA 标签的使用

术语 CDATA 指的是不应由 XML 解析器进行解析的文本数据(Unparsed Character Data)。在 XML 元素中,"<" 和 "&" 是非法的。

  • "<" 会产生错误,因为解析器会把该字符解释为新元素的开始。
  • "&" 也会产生错误,因为解析器会把该字符解释为字符实体的开始。

某些文本,比如 JavaScript 代码,包含大量 "<" 或 "&" 字符。为了避免错误,可以将脚本代码定义为 CDATA。

CDATA 部分中的所有内容都会被解析器忽略。CDATA 部分由 "" 结束:

在mapper文件中写sql语句时,遇到特殊字符时,如:< 等,建议使用标记,将sql语句包裹住,不被解析器解析

select t1.* from tbl_xxx t1 left join tbl_yyy t2 on t1.aa = t2.aa
where t2.Channel = #{channel}
<![CDATA[
        and to_char(t1.HU_DATE,'YYYYMMdd') <= to_char(sysdate,'YYYYMMdd')
        ]]>
and t1.EXECUTION_STATE != '1'
order by t1.HU_DATE

例如这里查询是需要用到大于等于这样的符号,但是XML中"<"符号是非法的,无法解析.后台也会报错,所以我们在这里用CDATA将SQL包裹起来。这样就可以正常进行解析了。

Mybatis都有哪些Executor执行器?

Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。

  • SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

  • ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。

  • BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。

Mybatis能执行一对一、一对多的关联查询

一对一:association

<!--   
    4、关联表查询:一对一关联  
    如何根据id查询班级信息(包括老师信息)  
    Class封装了Teacher属性,即是相互关联的  
 -->  
<!--定义操作 users 表的sql 映射文件:orderMapper.xml   -->  
<mapper namespace="com.mybatis.test4.classesMapper">  
    <!--  
        方式一:嵌套结果  
        使用嵌套结果映射来处理重复的联合结果的子集来封装联表查询的数据(去除重复的数据)  
    -->  
            <select id="getClassInfo" parameterType="int" resultMap="ClassResultMap">  
                select * from class c,teacher t where c.teacher_id = t.t_id and c.c_id = #{id}  
            </select>  
            <!-- 解决字段名属性名不一致问题 -->  
            <resultMap type="Classes" id="ClassResultMap">  
                <id property="id" column="c_id"/>  
                <result property="name" column="c_name"/>  
                <!-- 一对一关联查询 -->  
                <association property="teacher" column="teacher_id" javaType="Teacher">  
                    <id property="id" column="t_id"/>  
                    <result property="name" column="t_name"/>  
                </association>  
            </resultMap>  
      
    <!--  
        方式二:嵌套查询  
        通过执行另外一个SQL映射语句来返回预期的复杂类型:  
        SELECT * FROM class WHERE c_id =1;  
        SELECT * FROM teacher WHERE t_id =1;//1 是上一个查询得到的teacher_id的值  
    -->  
    <select id="getClassInfo2" parameterType="int" resultMap="ClassResultMap2" >  
        select * from class where c_id = #{id}  
    </select>  
      
    <!-- 解决字段名属性名不一致问题 -->  
    <resultMap type="Classes" id="ClassResultMap2">  
        <id property="id" column="c_id"/>  
        <result property="name" column="c_name"/>  
        <association property="teacher" column="teacher_id"   
                    javaType="Teacher" select="getTeacher">  
        </association>  
    </resultMap>  
      
    <select id="getTeacher" parameterType="int" resultType="Teacher">  
        select t_id id,t_name name from teacher where t_id=#{id}  
    </select>  
      
</mapper>

一对多:collection

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE  mapper  PUBLIC  "-//mybatis.org//DTD  Mapper  3.0//EN"  
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<!--   
    4、关联表查询:一对多关联  
    如何根据class_id查询班级信息(包括老师和学生信息),学生信息为集合List  
    Class封装了Teacher和学生属性,即一张class表中包含teacher表和student表  
 -->  
<!--定义操作 classes 表的sql 映射文件:classesMapper.xml   -->  
<mapper namespace="com.mybatis.test5.classesMapper2">  
    <!--   
        方式一:嵌套结果  
        使用嵌套结果映射来处理重复的联合结果的子集  
        SELECT * FROM class c, teacher t,student s   
        WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id AND c.c_id=1  
    -->  
    <select id="getClassInfo3" parameterType="int"  
            resultMap="getClassMap">  
            SELECT * FROM class c, teacher t,student s   
            WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id AND  c.c_id=#{id}  
    </select>  
    <!-- 解决字段名和属性不一致冲突 -->  
    <resultMap type="Classes" id="getClassMap">  
        <id property="id" column="c_id"/>  
        <result property="name" column="c_name"/>  
          
            <!-- 关联的教师信息 -->  
        <association property="teacher" column="teacher_id"   
                     javaType="Teacher">  
            <id property="id" column="t_id"/>  
            <result property="name" column="t_name"/>  
        </association>  
            <!-- 关联的学生信息,是集合 -->  
        <collection property="students"   
                    ofType="Student">  
            <id property="id" column="s_id"/>  
            <result property="name" column="s_name"/>   
        </collection>  
    </resultMap>  
      
    <!--   
        方式二:嵌套查询  
        通过执行另外一个SQL映射语句来返回预期的复杂类型  
        SELECT * FROM class WHERE c_id =1 //查询后获取到teacher_id,c_id值,传入下两条语句  
        SELECT * FROM teacher WHERE t_id =1   //t_id=1 是上条查询得到的teacher_id值  
        SELECT * FROM student WHERE class_id =1   //c_id = 1 是上条查询得到的c_id值  
    -->  
    <select id="getClassInfo4" parameterType="int"  resultMap="getClassMap2">  
            SELECT * FROM class WHERE c_id =#{id}     
    </select>  
          
        <resultMap type="Classes" id="getClassMap2">  
            <id property="id" column="c_id"/>  
            <result property="name" column="c_name"/>  
            <association property="teacher" column="teacher_id" javaType="Teacher"  
                        select="getTeacher"></association>  
            <collection property="students" column="c_id" ofType="Student"  
                        select="getStudent"></collection>  
        </resultMap>  
      
    <select id="getTeacher"  resultType="Teacher">  
            SELECT t_id id,t_name name FROM teacher WHERE t_id =#{id}  
    </select>  
      
    <select id="getStudent"  resultType="Student">  
            SELECT s_id id,s_name name FROM student WHERE class_id =#{id}                                                                                     
    </select>  
</mapper>

Dao接口里的方法,参数不同时,方法能重载吗

不能重载。因为在进行xml配置的时候会跟Dao中的方法名一一对应。xml中只能配置一个标签和对应方法匹配。(在Mybatis中,每一个<select><insert><update><delete>标签,都会被解析为一个MappedStatement对象,然后存储在全局Configration对象中,然寻找这个MappedStatement的逻辑是使用Dao的全限定名加上方法名,所以不参数的方法还是会找到同一个MappedStatement)。

${}和#{}的区别是什么

对于${},解析器会直接使用属性值替换,对于#{},MyBatis的解析器会先替换成?占位符,在sql执行前会使用PreparedStatement的参数设置方法,按序给sql的?号占位符设置参数值。

if条件判断

根据前台传送的参数进行动态的sql判断。

<select id="selectXXXX" parameterType="string" resultMap="BaseResultMap">
	select *
	from abs_senti_info
	<where>
		name = #{assetName}
		<if test=" score == -1 ">
			<![CDATA[AND senti_score < 0
		]]>
		</if>
		<if test=" score == 1 ">
			AND senti_score > 0
		</if>
	</where>
</select>
           

遍历 map中的list,并使用in

orgID:为传过来的map中的list的key值
item:是遍历之后的key值
open:开始的标签, (
close:结束的标签,)
separator:每次遍历结束之后,末尾会添加,

<foreach collection="orgID" item="orID"  open="(" close=")" separator=",">
		#{orID}
</foreach>

in查询中判断数组不为null且长度大于0

<select id="selectByIds" parameterType="java.util.Map" resultMap="BaseResultMap">
	select
	<include refid="Base_Column_List"/>
	from user_info
	<where>
		<if test="roleIds != null and roleIds.size() > 0">
			and role_id in
			<foreach collection="roleIds" index="index" item="item" open="(" separator="," close=")">
				#{item}
			</foreach>
		</if>
		<if test="userName != null and userName != ''">
			and user_name like '%'||#{userName,jdbcType=VARCHAR}||'%'
		</if>
	</where>
</select>

对于上面的like查询,最好使用concat函数

 <if test="xxx!= null and xxx!= ''">
      and user_name like concat('%',#{xxx,jdbcType=VARCHAR},'%')
 </if>

mybatis用Map返回的字段全变大写的问题

mybatis通常情况都是用javabean作为resultType的对象,但是有时也可以使用Map去接收。

<select id="execute" parameterType="String" resultType="java.util.HashMap">
        ${value}
</select>

如果使用Map,返回来的字段名全是大写,处理方法

Select name as "name" from v_zhyl_zxzf_hqyzflb

别名字段加上双引号就可以了。

posted @ 2020-03-31 17:24  程序员自由之路  阅读(942)  评论(0编辑  收藏  举报