zoukankan      html  css  js  c++  java
  • MyBatis源码分析(二)

    MyBatis的xml配置(核心配置)

    configuration(配置)
       properties(属性)
       settings(设置)  
       typeAliases(类型别名)
       typeHandlers(类型处理器)
       objectFactory(对象工厂)
       plugins(插件)
       environments(环境配置)
            environment(环境变量)
                transactionManager(事务管理器)
                dataSource(数据源)
      databaseIdProvider(数据库厂商标识)
      mappers(映射器)                

    MyBatis的Mapper映射

    Mapper映射文件只有几个顶级元素(按照应被定义的顺序如下):
    cache – 对给定命名空间的缓存配置。
    cache-ref – 对其他命名空间缓存配置的引用。
    resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
    sql – 可被其他语句引用的可重用语句块。
    insert – 映射插入语句
    update – 映射更新语句
    delete – 映射删除语句
    select – 映射查询语句

    MyBatis也可以使用注解开发

    生成代码时候,配置:
    <javaClientGenerator type="ANNOTATEDMAPPER"...
    生成注解代码,不生成xml代码了

    MyBatis开发使用注解还是xml?

    方式 优点 缺点
    Xml Xml与接口分离,方便管理,复杂的SQL不影响代码的可读性 过多的Xml配置文件
    Annotation 接口就能看到SQL语句,可读性强,不需要去找xml文件,方便 代码和SQL混杂,复杂一点过于混乱

    MyBatis批量插入

    1 普通for循环(此种方式对于数据库的I/O过于频繁,不适合大数据量的操作)

    for (int i = 0; i < 500; i++) {
        user = new User();
        user.setId("id" + i);
        user.setName("name" + i);
        userMapper.insert(user);
    }

    2 ExeutorType.BATCH(设置批量模式),把SQL语句发个数据库,数据库预编译好,然后数据库等待需要运行的参数,接收到参数一次性运行

    session = sqlSessionFactory.openSession(ExecutorType.BATCH, true);
    for (int i=0; i<500; i++) {
        UUserInfo userInfo = new UUserInfo();
        userInfo.setPhone("1346262122" + i);
        userInfo.setUserName("" + i);
        uUserInfoMapper.insert(userInfo);
    }

    3 传入一个数组或集合,标签<foreach>插入

     <foreach item="item" collection="strs.split(',')" separator="," open="(" close=")">
                #{item}
      </foreach>
    方式 性能 说明
    For循环 性能低,IO高  
    ExeutorType.BATCH 性能居中  
    <foreach>标签拼SQL 性能最高

    有SQL长度限制,mysql默认接收SQl的长度为10486576(1M),该方式若超过1M

    会抛出异常

    MyBatis联合查询

      一对一关系

      在一对一关系中,A表中的一行最多只能匹配B表的一行,反之亦然.这种关系并不常见,因为一般来说,这种关系的信息会保存在一张表中,当然也可以利用一对一关系来保存,比如分割具有多列的表.(如:一个人只有一个身份证) 

    <association>标签

    <resultMap id="OneToOneBaseResultMap" type="com.test.mybatis.model.Person">
      <id column="id" jdbcType="INTEGER" property="id" />
      <result column="nick" jdbcType="VARCHAR" property="nick" />
      <result column="phone" jdbcType="VARCHAR" property="phone" />
      <result column="sex" jdbcType="INTEGER" property="sex" />
      <association property="idCard" javaType="com.test.mybatis.model.IdCard">
        <id column="id" jdbcType="INTEGER" property="id" />
        <result column="personId" jdbcType="INTEGER" property="personid" />
        <result column="realName" jdbcType="VARCHAR" property="realname" />
        <result column="idCard" jdbcType="VARCHAR" property="idcard" />
      </association>
    </resultMap>

      一对多关系

      一对多是最普通的一种关系,在这种关系中,A表的一行可以匹配B表中的多行,但是B表中的一行只能匹配A表中的一行.举例:(一个部门可以有多个员工)

      <collection>标签

    <resultMap type="com.mybatis.bean.Department" id="MyDept">
            <id column="did" property="id"/>
            <result column="dept_name" property="departmentName"/>
            <!-- 
                collection定义关联集合类型的属性的封装规则 
                ofType:指定集合里面元素的类型
            -->
            <collection property="emps" ofType="com.mybatis.bean.Employee">
                <!-- 定义这个集合中元素的封装规则 -->
                <id column="eid" property="id"/>
                <result column="last_name" property="lastName"/>
                <result column="email" property="email"/>
                <result column="gender" property="gender"/>
            </collection>
        </resultMap>

      多对多关系

      在多对多的关系中,A表的一行可以匹配B表的多行.反之亦然.要创建这种关系,需要定义第三张表,也可以称之为结合表或者关系表.它的主键是由A表和B表的外部键组成.  举例(一个用户有多个角色,一个角色可以对应多个用户)  

     <collection>标签

    MyBatis插入并返回主键

      方式一:(数据库要设置主键自增长)

    <insert id="insertSelective" useGeneratedKeys="true" keyProperty="id" keyColumn="id"
     parameterType="com.test.mybatis.model.UUserInfo">


    useGeneratedKeys="true"表示使用主键自增  keyProperty="id"表示将主键自增后的主键值赋值给实体类中的id属性
    parameterType="com.test.mybatis.model.UUserInfo" 实体类,自增后的主键值将会赋值给该实体类的id属性

      方式二:(一般用在<insert>标签里面)

    <selectKey keyProperty="id" resultType="integer" order="AFTER">
      SELECT LAST_INSERT_ID()
    </selectKey>
     SELECT LAST_INSERT_ID()表示查询出刚刚插入的的记录自增长id  order='AFTER' 表示先执行插入语句,之后再执行查询语句

    MyBatis的SQL注入攻击
      注入攻击的危害
      1:数据库被拖库(把数据从数据库拉取出来,造成数据泄露)
      2.重要信息被泄露
    注入的本质是把用户输入的数据当做有效代码执行.
    Mybatis的预编译机制可以有效防止SQL注入攻击.
      '#{}''${}'的区别:
    '#{}':MyBaits会首先对其进行预编译,将#{user_ids}替换成?占位符,然后在执行时替换成实际传入的user_id值,**并在两边加上单引号,以字符串方式处理。
    '${}':简单的字符串拼接
    栗子:
    uUserInfoMapper.selectByIn("select user_name from u_user_info");
    where user_name in (${userName})
    可使用MyBatis自带循环标签解决SQL语句动态拼接的问题:
    select * from news where id in
    <foreach collection="ids" item="item" open="("separator="," close=")">
      #{item} 
    </foreach>

    MyBatis的自定义类型转换器(实现数据类型和数据库数据类型的映射关系 如:String和VARCHAR的对应关系)  需求:实现对数据库身份证存储的加密
    1、定义自己的HandlerType实现TypeHandler接口或者继承BaseTypeHandler类
    2、覆盖其四个方法;
    3、在核心配置文件mybatis-config.xml中配置<typeHandlers>标签或者在映射文件的增、改、查位置单独配置;
    
    <typeHandlers>
        <typeHandler javaType="com.test.mybatis.typehandler.UserIdCard" handler="com.bjpowernode.mybatis.typehandler.CryptTypeHandler"/>
    </typeHandlers>
    
    <result column="idCard" jdbcType="VARCHAR" property="userIdCard" javaType="com.bjpowernode.mybatis.typehandler.UserIdCard" 
    typeHandler="com.test.mybatis.typehandler.CryptTypeHandler"/> <if test="userIdCard != null"> #{userIdCard, jdbcType=VARCHAR, typeHandler=com.test.mybatis.typehandler.CryptTypeHandler}, </if>
    系统自带的类型转换器StringTypeHandler 
    public class StringTypeHandler extends BaseTypeHandler<String> {
    
      @Override
      public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
          throws SQLException {
        ps.setString(i, parameter);
      }
    
      @Override
      public String getNullableResult(ResultSet rs, String columnName)
          throws SQLException {
        return rs.getString(columnName);
      }
    
      @Override
      public String getNullableResult(ResultSet rs, int columnIndex)
          throws SQLException {
        return rs.getString(columnIndex);
      }
    
      @Override
      public String getNullableResult(CallableStatement cs, int columnIndex)
          throws SQLException {
        return cs.getString(columnIndex);
      }
    }
    MyBatis的动态SQL

      if   --判断标签

      choose (when, otherwise)  --多项选择 ,与页面的 jstl 标签非常类似

      trim (where, set)  --修剪、格式化,添加前后缀的一个标签

      foreach  --循环

    <select id="dynamicChoose" parameterType="News" resultType="News">
        select * from news where 1 = 1 
        <choose>
            <when test="title != null">
                and title = #{title}
            </when>
            <when test="content != null">
                and content = #{content}
            </when>
            <otherwise>
                and owner = "zhangsan"
            </otherwise>
        </choose>
    </select>

    MyBatis的SQL片段使用

      <sql id="Base_Column_List">
        id, name
      </sql>
     <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
            select
            <include refid="Base_Column_List"/>
            from user
            where id = #{id,jdbcType=INTEGER}
        </select>

    MyBatis的一级.二级缓存

      一级缓存是sqlSession级别,默认开启

      二级缓存是mapper级别,默认关闭,缓存命中率低

    MyBatis的事务管理:

    <transactionManager type="JDBC">
          <property name="..." value="..."/>
    </transactionManager>

    如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器, 因为 Spring 模块会使用自带的管理器来覆盖前面的配置.

  • 相关阅读:
    东拼西凑 vim配置-更新
    oh-my-zsh
    switch变种玩法
    每天一个linux命令(5):rm 命令
    每天一个linux命令(4):mkdir命令
    每天一个linux命令(3):pwd命令
    ES6学习之let
    Window.scrollTo()
    如何调整滚动条的样式
    移动端实现滚动的四种方案
  • 原文地址:https://www.cnblogs.com/zhaoletian/p/13267515.html
Copyright © 2011-2022 走看看