mybatis的使用

为什么需要预编译
1. 定义:
         SQL 预编译指的是数据库驱动在发送 SQL 语句和参数给 DBMS 之前对 SQL 语句进行编译,这样 DBMS 执行 SQL 时,就不需要重新编译。
2. 为什么需要预编译
       JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译。预编阶段可以优化 SQL 的执行。预编译之后的 SQL 多数情况下可以直接执行, DBMS 不需要再次编译,越复杂的SQL,编译的复杂度将越大,预编译阶段可以 合并多次操作为一个操作。同时预编译语句对象可以重复利用。把一个 SQL 预编 译后产生的 PreparedStatement 对象缓存下来,下次对于同一个SQL,可以直 接使用这个缓存的 PreparedState 对象。Mybatis默认情况下,将对所有的 SQL进行预编译。
Mybatis都有哪些Executor执行器?它们之间的区别是什 么?
        Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
       1、SimpleExecutor :每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
       2、ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
       3、BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所 有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
Mybatis中如何指定使用哪一种Executor执行器?
         在Mybatis配置文件中,在设置(settings)可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数,如SqlSession.openSession(ExecutorType.execType)配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。
映射器
#{}和${}的区别
        #{}是占位符,预编译处理;
        ${}是拼接符,字符串替换,没有预编译处理。
Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{} 替换为?号,调用PreparedStatement的set方法来赋值。
Mybatis在处理${},是原值传入,是原值传入,就是把{}替换成 变量的值,相当于JDBC中的Statement编译
变量替换后,#{} 对应的变量自动加上单引号 ‘’;
变量替换后,${}对应的变量不会加上单引号 ‘’
#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入;
#{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外;
#{}预编译会对特殊字符进行转义处理,如查询的参数是: 'abc 等能正常查询;
${}是直接替换参数,如查询参数是:'12 或 abc等会报错     

索引类型是数字,传入字符串不会失效,所以#{} 不会导致索引失效。

索引类型是字符串:传入数字会失效。

模糊查询like语句该怎么写
(1)’%${question}%’ 可能引起SQL注入,不推荐
(2)'%'||#{question}||'%' ,mysql中不可用   
(3)CONCAT(’%’,#{question},’%’) 使用CONCAT()函数
(4)使用bind标签
     < select  id =" listUserLikeUsername resultType =" com.jourwon.pojo.User ">
        < bind  name =" pattern value ="' % ' + username + ' % '"/>
              select id,sex,age,username,password from person where username LIKE #{pattern}
    </ select >
  
在mapper中如何传递多个参数
方法1:顺序传参法
public User selectUser ( String name , int deptId );
< select id ="selectUser" resultMap ="UserResultMap">
         select * from user where user_name = # { 0 } and dept_id = # { 1 }
</ select >
#{}里面的数字代表传入参数的顺序。
这种方法不建议使用,sql层表达不直观,且一旦顺序调整容易出错。
方法2:@Param注解传参法
public User selectUser (@Param( "userName" ) String name , int @Param( "deptId" ) deptId );
< select id ="selectUser" resultMap ="UserResultMap">
        select * from user where user_name = # { userName } and dept_id = # { deptId }
</ select >
#{}里面的名称对应的是注解@Param括号里面修饰的名称。
这种方法在参数不多的情况还是比较直观的,推荐使用。
方法3:Map传参法
public User selectUser ( Map < String , Object > params );
< select id ="selectUser" parameterType ="java.util.Map" resultMap ="UserResultMap">
        select * from user where user_name = # { userName } and dept_id = # { deptId }
</ select >
#{}里面的名称对应的是Map里面的key名称。
这种方法适合传递多个参数,且参数易变能灵活传递的情况。
方法4:Java Bean传参法
public User selectUser ( User user );
< select id ="selectUser" parameterType ="com.jourwon.pojo.User" resultMap ="UserResultMap">              select * from user where user_name = # { userName } and dept_id = # { deptId }
</ select >
#{}里面的名称对应的是User类里面的成员属性。这种方法直观,需要建一个实体类,扩展不容易,需要加属性,但代码可读性 强,业务逻辑处理方便,推荐使用。
Mybatis常用标签:
foreach
        foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。
        foreach标签的属性主要有item,index,collection,open,separator,close。
                collection 表示传入的集合参数名;
                item 表示集合中每一个元素进行迭代时的别名,随便起的变量名;
                index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置,不常用;
                open 表示该语句以什么开始,常用“(”;
                separator表示在每次进行迭代之间以什么符号作为分隔符,常用“,”;
                close 表示以什么结束,常用“)”。
        1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
        2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
        3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在 MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
list和array的用法,proIdList为参数名:

List<Map>的用法:

//推荐使用
< insert  id =" addEmpsBatch ">
        INSERT INTO emp(ename,gender,email,did) VALUES
        < foreach  collection =" emps item =" emp separator =" , ">
         (#{emp.eName},# {emp.gender},#{emp.email},#{emp.dept.id})
       </ foreach >
</ insert >
< insert  id =" addEmpsBatch ">
        < foreach  collection =" emps " item =" emp " separator =" ; ">
              INSERT INTO emp(ename,gender,email,did) VALUES(#{emp.eName},# {emp.gender},#{emp.email},#{emp.dept.id})
        </ foreach >
</ insert >
choose+when+otherwise
    mybatis中没有if-else语法,用法如下:  

使用sql片段
       sql标签: 将公用的sql写在sql标签中,用的时候通过id引用

                   <sql id="selectid">
                       select * from emp
                   </sql>

                   <select id="selectEmpsByList"  parameterType="java.util.Map" resultType="emp">
                         <include refid="selectid"/>
                      <where>
                          user_name= #{userName}
                      </where>
                    </select>  

一对一 和一对多标签:association 和 collection

 

Mybatis是否支持延迟加载?如果支持,它的实现原理是 什么?
        Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
        它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦 截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
        
      不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。

别名:

        1、给java的实体类起别名,在sql中的paramType或resultType使用别名即可

                 <typeAliases>
                          <typeAlias alias="dept" type="com.msb.pojo.Dept"/>
                 </typeAliases>

         2、给包名设置别名,在全局配置文件中配置

                   (1)、包下面的实体类如果有@Alias("author"),则以注解的内容作为别名

                   (2)、包下面的实体类没有@Alias,该实体类的别名就是实体类首字母小写的名字

                          <typeAliases>
                                  <package name="com.msb.pojo"/>
                          </typeAliases> 

缓存:

        一级缓存:sqlSession级别的,也就是一个事物中查询一次后后面再次查询就从缓存中获取,一级缓存是mybatis默认支持的,不需要配置;

        二级缓存:sqlSessionFactory级别,也就是所有事物共享的,默认是不启动的,需要手动配置: <setting name="cacheEnabled" value="true"/>

数据库自增主键的使用:适用于mysql 和 sql server

        <insert id="insertAuthor" useGeneratedKeys="true"  keyProperty="id">
              insert into Author (username,password,email,bio)
                 values (#{username},#{password},#{email},#{bio})
       </insert>

mybatis的逆向工程:

       根据数据库表生成 xml、dao、pojo

       demo见链接:https://pan.baidu.com/s/10bWrU9DcPnacfLBEME4Z-w?pwd=yb46 

       生成代码的路径,使用相对路径  .\src 不起作用,所以改成了全路径

       以下是生成的方法,默认都是true

              前面五个是生成的使用例子,生成的例子很难看懂,一般情况下不使用,

              后面的增删改查方法根据需要生成

Mybatis的返回值说明
      mybatis的返回值常用的有三种:bean、map、String\Long\Double等,mybatis对bean和map的返回实现方式是通过ObjectWrapper不同的实现类实现的
      bean:
          1、首先将bean中的所有字段保存在map(key是字段全部转大写,value是原值,如(USERID,userId))中;
          2、然后将查询出的字段(默认都是大写)替换掉下划线,然后根据这个字段去上面的map找到value,然后根据这个value调用set方法进行属性赋值

    Map:
           Map默认使用MapWrapper,sql中写的字段名是什么就返回什么,不做调整;
           mybatis提供了另一个实现类MybatisMapWrapper,用于将查询出的字段转化为驼峰命名,有以下两种实现:
               1、按下图中注入bean,此时空值就查不出来了;
               2、在mybatis的配置文件中进行配置:
                      开启驼峰命名:map-underscore-to-camel-case: true
                      将空值也查询出来:call-setters-on-nulls: true

String\Long\Double
      
      这几种方式不需要字段名称的转换,返回的就是一个值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值