mybatis 学习笔记

1.mybatis返回主键的值:{

<insert id="XXX">
    insert into sys_user(
        id,user_name,user_password,user_email,
        user_info,head_img,create_time
    )
    values(
        #{id},#{userName},#{userPassword},#(userEmail),
        #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
    )
</insert>

·Mysql:{


    1)适用于主键值自增(数据库主键数据类型为int或者Long){
        ·修改配置文件
        <insert id="XXX" useGeneratedKeys="true",keyProperty="id">
            insert into sys_user(
                id,user_name,user_password,user_email,
                user_info,head_img,create_time
            )
            values(
                #{id},#{userName},#{userPassword},#(userEmail),
                #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
            )
        </insert>
        
        ·在对应的接口中将方法的返回值设定为对应的返回值。
    }
    
    2)适用于所有的情况:{
    
        ·修改配置文件
            <insert id="XXX">
                insert into sys_user(
                    id,user_name,user_password,user_email,
                    user_info,head_img,create_time
                )
                values(
                    #{id},#{userName},#{userPassword},#(userEmail),
                    #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
                )
                
                <selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER">
                    SELECT LAST_INSERT_ID()
                </selectKey>
            </insert>
    
        ·在对应的接口中将方法的返回值设定为对应的返回值即可
    }

}

Oracle:{


    ·修改配置文件
            <insert id="XXX">
                <selectKey keyColumn="id" resultType="long" keyProperty="id" order="BEFORE">
                    SELECT SEQ_ID.nextval from dual
                </selectKey>
                
                insert into sys_user(
                    id,user_name,user_password,user_email,
                    user_info,head_img,create_time
                )
                values(
                    #{id},#{userName},#{userPassword},#(userEmail),
                    #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
                )
            </insert>
    
        ·在对应的接口中将方法的返回值设定为对应的返回值即可

}

注意:类似于Mysql第二种方式,或者是Oracle的返回主键值的方式<selectKey>标签执行的顺序仅仅和改标签配置的
      order属性值相关,和它在insert语句的前后顺序无关;
      其他一些支持逐渐自增数据库配置selectKey中回写主键的sql可查阅《Mybatis从入门到精通 刘增辉著》第二章,p42.

}

2.使用map或者@Param注解来解决多个接口参数的问题{
·当接口对应的方法中只有一个参数时,Mybatis并不关心参数叫什么名字就会把这个唯一的参数值拿来使用;
·当接口对应的方法中有多个入参时,若没有使用@Param注解来标识参数名,那么Mybatis默认可用的参数名只有
[0,1,param1,param2]
·当多接口参数中使用了@Param注解来标识参数名,那么Mybatis便可识别对应在注解中标识的参数.
}

3.mybatis 模糊查询(like):{
·普通SQL
<select id="XXX">
select *
from sys_user u
where u.user_name like concat('%',#{userName},'%')
and u.user_email=#{userEmail}
</select>

·动态SQL
<select id="XXX">
    select * 
    from sys_user u
    where 1=1
    <if test="userName !=null and userName!='' ">
        and u.user_name like concat('%',#{userName},'%')
    </if>
    <if test"userEmail!=null and userEmail!='' ">
        and u.user_email = #{userEmail}
    </if>
</select>

}

4.动态SQL:{

1)if{

    ·在where子句中使用if(例如上述笔记的like模糊查询)
    
    ·在UPDATE中使用if{
        <update id="XXX">
            update sys_user
            set
                <if test="userName!=null and userName!='' ">
                    user_name = #{userName},
                </if>
                <if test="userPassword!=null and userPassword!='' ">
                    user_password = #{userPassword},
                </if>
                <if test="userEmail!=null and userEmail!='' ">
                    user_email = #{userEmail},
                </if>
                <if test="userInfo!=null and userInfo!='' ">
                    user_info = #{userInfo},
                </if>
                <if test="headImg!=null">
                    head_img = #{headImg,jdbcType=BLOB},
                </if>
                id = #{id}
            where id=#{id}
        </update>
    }
    
    ·在INSERT动态插入中使用if:{
    
        <insert id="XXX" useGeneratedKeys="true" keyProperty="id">
            
            insert into sys_user(
                id,user_name,user_password,
                <if test="userEmail!=null and userEmail!=''">
                    user_email,
                </if>
                user_info,head_img,create_time
            )
            values(
                #{id},#{userName},
                <if test="userEmail!=null and userEmail!=''">
                    #(userEmail),
                <if>
                #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
            )
        </insert>
    }


}


2)choose提供if...else、if...else...的逻辑:{

    需求:当参数id有值的时候优先使用id进行查询,当id没有值的时候就判断userName是否有值,如果用户名有值
          就使用用户名查询,如果用户名也没有值那就使SQL查询无结果。
          
    <select id="XXX">
        select * 
        from sys_user u
        where 1=1
        <choose>
            <when test="id !=null">
                and id= #{id},
            </when>
            <when test="userName !=null and userName!=''">
                and user_name= #{userName},
            </when>
            <otherwise>
                and 1=2
            </otherwise>
        </choose>
    </select>
    
}


3)where、set、trim{

    1)where{
    
        <select id="xxx">
            select * 
            from sys_user
            <where>
                <if test="userName!=null and userName!=''">
                    and user_name = #{userName}
                </if>
                <if test="userEmail!=null and userEmail!=''">
                    and user_email = #{userEmail}
                </if>
            </where>
        </selcet>
        
        注意:使用<where>标签,当所有的if条件都不满足的时候,最终生成的SQL语句中不会出现where子句,这就保证了
              程序中永远不会出现where 1= 1 这样的情况;
              where元素内容就是以and开头的条件,where会自动去掉开头的and.
    }
    
    
    
    2)set{
    
        <update id="xxx">
            update sys_user
            <set>
                <if test="userName!=null and userName!=''">
                    user_name = #{userName},
                </if>
                <if test="userPassword!=null and userPassword!=''">
                    user_name = #{userName},
                </if>
                <if test="userEmail!=null and userEmail!=''">
                    user_email = #{userEmail},
                </if>
                <if test="userInfo!=null and userInfo!=''">
                    user_info = #{userInfo},
                </if>
                id = #{id}
            </set>
            where id =#{id}
        </updae>
        
        注意:如果set标签包含的元素有返回值,就插入一个set;
              如果set后面的字符串是以逗号结尾的,就将这个逗号剔除;
              如果set中的元素没有内容,那么生成的SQL还是会有SQL语法错误,故此类似id=#{id}这样的赋值任然还有必要保留
    
    }
    
    
    
    3)trim{
    
        <trim prefix="WHERE" prefixOverrides="AND |OR">
            ...
        
        </trim>
        
        trim标签有如下的属性:
                                prefix:当trim元素内包含内容时,会给内容增加prefix指定的前缀。
                                prefixOverrides:当trim元素包含内容时,会把内容中匹配的前缀字符串去掉。
                                suffix:当trim元素内包含内容时,会给内容增加suffix指定的后缀。
                                suffixOverrides:当trim元素包含内容时,会把内容中匹配的后缀字符串去掉。
    }
    
    
}

4)foreach{

foreach实现in集合:{
        <select id="xxx">
            select * 
            from sys_user
            where id in
            <foreach collection="list" open="(" close=")" separator="," item="id" index="i">
                #{id}
            </foreach>
        </select>
    }       
    
    注意:
        ·当只有一个数组参数或者一个结婚参数的时:
                当参数类型为集合(Collection)类型时,默认在Mybatis底层会将其转换为Map类型,并添加
                一个key为collection的值;
                当参数是一个list集合类型时,也会默认转换成map类型,默认的key为list;
                当参数类型为数组时,也会默认转换成map类型,默认的key为array.
          
          ·有多个参数:
                使用@Param注解来给每个参数指定一个名字,将collection的值设置为@Param指定的注解的名称即可.
          
          ·参数是Map类型:    
                使用Map类型和使用@Param注解的情形类似只要将map的key的值绑定给collection的属性即可;
                如果要循环所输入的Map,推荐使用@Param注解指定名字,此时可以将collection的值设置为@Param注解指定的名字即可,如果不想指定名字,则使用_parameter.
          
          ·参数是一个对象:
                这种情况下指定collection属性值为对象的属性名即可,当使用对象内多层嵌套的对象时,使用属性.属性(集合和数组可以使用下标取值),可以指定深层次的属性值.
                
                
                
                
    foreach实现批量插入:{
        
        <insert id="XXX" useGeneratedKeys="true" keyProperty="id">
            
            insert into sys_user(
                user_name,user_password,user_email,
                user_info,head_img,create_time
            )
            values
            <foreach collection="list" item="user" separator=",">
                (
                    #{userName},#{userPassword},#{userEmail},
                    #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP}
                )
            </foreach>
        </insert>
    }
    
    
    foreach实现动态update:{
    
        <update id="xxx">
            update sys_user
            set
            <foreach collection="_parameter" item="val" index="key" separator=",">
                ${key}= #{val}
            </foreach>
        </update>
        
        
        注意:当参数为map类型时,foreach标签的index属性值对应的不是索引值,而是map中的key;
              如上以map的key作为列名,对应的值作为该列的值,通过foreach将需要更新的字段拼接在SQL语句中。
    }
}


5)bind用法:{

    ·bind可以使用OGNL创建一个变量并将其绑定到上下文中;
    ·例子:修改之前的like模糊查询:{
    
        未修改之前:{
            <if test="userName!=null and userName!=''">
                and user_name like concat('%',#{userName},'%')
            </if>
        }
        在未修改之前的版本中为使用like模糊查询,使用了concat函数来实现字符串拼接,在MySql中这个函数支持多个参数,但是在Oracle中这个函数
        只支持两个参数;由于不同数据库之间语法的差异,如果更换数据库,有些SQL语句就可能需要重写,针对这种情况可以使用bind标签来避免由于
        更换数据库而带来的麻烦。
        
        修改后:{
            
            <if test="userName!=null and userName!='' ">
                <bind name="userNameLike" value="'%'+userName+'%'"/>
                and user_name like #{userNameLike}
            </if>
            
            注意:bind标签的两个属性都是必选项,name为绑定到上下文的变量名,value为OGNL表达式。
        }
        
    }
}

}

5.mybatis二级缓存配置:{

}

6.mybatis高级映射:{

1)mybatis单表查询:{

    ·单表查询时可以使用字段别名来实现查询返回结果集和JavaBean的映射;
    ·可以通过配置resultMap来实现映射;
    ·如果数据库字段和JavaBean符合转驼峰规则,通过在mybatis中配置全局属性:
        <settings>
            <!--
                通过将该属性配置为true可以自动将以下划线方式命名的数据列映射到Java对象的驼峰式命名属性中,
                该属性默认值为false,如果想要使用该功能,需要手动指配其值为true。
            -->
            <setting name="mapUnderscoreToCamelCase" value="true" />
            <!--其他配置-->
        </settings>
}

2)一对一映射:{

    eg:{
    
        package com.hsun.mybatis.model.SysUser;
        public class User{
        
            private String userName;
            
            private String userPassword;
            
            private SysRole role;//SysRole是一个实体类
            //setter、getter
        }
        
        
        ·使用别名映射
            <select id="xxx"> 
                
                selcet 
                    u.user_name,
                    u.user_password,
                    r.id "role.id",
                    r.role_name "role.roleName"
                from sys_user u
                inner join sys_user_role ur on u.id = ur.user_id
                inner join sys_role r on ur.role_id = r.id
                where u.id = #{id}
            </selcet>
            
            注意:上述方法中sys_role 查询列的别名都是"role."前缀,通过这种方式,将role的属性都映射到了
                  SysUser的role属性上。
            
        ·使用resultmap映射
            <resultMap id="userAndRoleResultMap" type="com.hsun.mybatis.model.SysUser">
                <id property="id" column="id" />
                <result property="userName" column="user_name"/>
                <result property="userPassword" column="user_password"/>
                
                <!--sys_role相关属性-->
                <result property="role.id" column="role_id" />
                <result property="role.roleName" column="role_name" />
                
            </resultMap>
            
            注意:该种配置在property属性中使用“role."前缀,column部分为了避免不同表中存在相同的列,所有可能重名
                  的列都加了"role_"前缀,使用这种配置的时候还要在查询时使用不同的别名。查询语句如下:
            
            <select id="xxx" resultMap="userAndRoleResultMap"> 
                
                selcet 
                    u.user_name,
                    u.user_password,
                    r.id role_id,
                    r.role_name
                from sys_user u
                inner join sys_user_role ur on u.id = ur.user_id
                inner join sys_role r on ur.role_id = r.id
                where u.id = #{id}
            </selcet>
            
            
            
        ·使用resultMap标签的association标签来配置一对一映射
            <!--userResultMap仅仅配置了user的属性不包含role属性-->
            <resultMap id="userAndRoleWithAssociationResultMap" extends="userResultMap"
             type="com.hsun.mybatis.model.SysUser">
                <id property="id" column="id" />
                <result property="userName" column="user_name"/>
                <result property="userPassword" column="user_password"/>
                
                <association property="role" javaType="com.hsun.mybatis.model.SysRole"
                 columnPrefix="role_">
                     <!--sys_role相关属性-->
                    <result property="id" column="role_id" />
                    <result property="roleName" column="role_name" />                       
                </association>
            </resultMap>
            
            注意:
                ·property:实体类中的属性名,必选项,
                ·javaType:属性对应的Java类型。
                ·resultMap:可以使用现有的resultMap,而不需要在association标签中配置result
                ·columnPrefix:查询列的前缀,配置前缀后,在子标签result的column可以省略前缀。
                                但是在查询时,role对应的查询列都要使用别名并且别名必须是以此处配置的前缀开头的。
                                
                ·在mybatis中不同命名空间下的resultMap也是可以引用的,引用时需要加上”命名空间.resultMap的id属性“
                    例如:有关role的属性全部配置到RoleMapper.xml 文件中,其中有一个resultMap的id为roleMap,那么在
                           UserMapper.xml文件中引用的方式如下:
                           
                            <resultMap id="userAndRoleWithAssociationResultMap" extends="userResultMap"
                             type="com.hsun.mybatis.model.SysUser">
                                <id property="id" column="id" />
                                <result property="userName" column="user_name"/>
                                <result property="userPassword" column="user_password"/>
                                
                                <association property="role" resultMap="com.hsun.mybatis.model.RoleMapper.roleMap"
                                 columnPrefix="role_" />
                            </resultMap>
    }
    
    ·association标签嵌套查询:{
    
        ·association标签的嵌套查询常用的属性如下:{
            select:另一个映射查询的id,mybatis会额外执行这个查询获取嵌套对象的结果.
            column: 列名(或别名),将主查询中列的结果作为嵌套查询的参数,配置方式如:
                    column={prop1=col1,prop2=col2},prop1,prop2将作为嵌套查询的参数.
            ·fetchType:数据加载方式,可选值为lazy和eager,分别为延迟加载和积极加载,这个配置
                        会会覆盖全局的lazyLoadingEnabled配置。
                        
                        
            <resultMap id="xxx" extends="userMap" type="com.hsun.mybatis.model.User">
                <association property="role"
                    fetchType="lazy"
                    selcet="com.hsun.mybatis.mapper.RoleMapper.selcetRoleById"
                    column="id={role_id}">
                </association>
            <resultMap/>
            
        }
    }

    
}


3)一对多映射:{

    使用collection集合的嵌套映射:
        
        <resultMap id="userRoleListMap" extends="userResultMap"
            type="com.hsun.mybatis.model.SysUser">
            <id property="id" column="id" />
            <result property="userName" column="user_name"/>
            <result property="userPassword" column="user_password"/>
            
            <collection property="roleList" ofType="com.hsun.mybatis.model.SysRole"
             columnPrefix="role_">
                 <!--sys_role相关属性-->
                <result property="id" column="role_id" />
                <result property="roleName" column="role_name" />                       
            </collection>
        </resultMap>
        
        或者:
        
        <resultMap id="userRoleListMap" extends="userResultMap"
            type="com.hsun.mybatis.model.SysUser">
            <id property="id" column="id" />
            <result property="userName" column="user_name"/>
            <result property="userPassword" column="user_password"/>
            
            <collection property="roleList" ofType="com.hsun.mybatis.model.SysRole"
             columnPrefix="role_" resultMap="com.hsun.mybatis.mapper.SysRoleMapper.roleMap">
            </collection>
        </resultMap>
    
}

}

7.mybatis 部分常用settings配置:{

<settings>
            <!--
                通过将该属性配置为true可以自动将以下划线方式命名的数据列映射到Java对象的驼峰式命名属性中,
                该属性默认值为false,如果想要使用该功能,需要手动指配其值为true。
            -->
            <setting name="mapUnderscoreToCamelCase" value="true" />
            
            <!--指定使用LOG4J来支持mybatis的日志-->
            <setting name="logImpl" value="LOG4J" />
            
            <!--
                mybatis 二级缓存全局开关,默认为开启状态,mybatis的二级缓存是和命名空间绑定的,即二级缓存需要配置在Mapper.xml、
                文件中或者配置在Mapper.java接口中。配置在xml文件中,命名空间就是xml根节点mapper的namespace属性。在mapper接口中,
                命名空间就是接口的全限定名称。
            -->
            <setting name="cacheEnabled" value="true" />
            
            <!-- 
                ·该属性是控制mybatis带有延迟加载属性的对象的完整加载或者延迟加载;
                ·当改该属性的值为true时,会使得对任意延迟属性的调用会使带有延迟加载属性的对象完整加载:
                ·当该属性的值为false时,会对带有延迟加载属性的对象按需加载;
                ·该属性的默认值是true,故而要使用mybatis的延迟加载属性需要手动在<settings>标签中将该值配置为false;
                ·mybatis的延迟加载是通过动态代理实现的,在与spring集成时,要确保带有延迟加载的属性的对象的获取在
                 service层。当结果从service层返回controller层时,如果获取延迟加载的属性值,会因为SqlSession已经关闭而抛出异常.
            -->
            <setting name="agressivelazyLoading" value="false" />
            
        </settings>

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 官方文档 简介 入门 XML配置 XML映射文件 动态SQL Java API SQL语句构建器 日志 一、 JD...
    拾壹北阅读 3,540评论 0 52
  • 《深入浅出MyBatis技术原理与实战》2016年版本 读书笔记 第一章 MyBatis简介 1.ORM模型:对象...
    GunnerAha阅读 542评论 0 3
  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,423评论 0 4
  • 在无端的暗黑中喧闹 挽留的几角光 折透的玻璃窗 隐隐 闪闪 月下躲藏的流年 晶莹着的 溪水的声响 几时的风 裹携着...
    素锦风阅读 179评论 2 1
  • 最初对川久保玲的认识是在一次朋友的聚会上,他穿了一件印有经典红心LOGO的卫衣,我问他这是你刚买的CDG吗,他笑...
    husaki阅读 5,142评论 1 51