Mybatis进阶

1.数据库的环境切换

2.注解方式

​## 推荐使用xml

a.将sql语句写在接口的方法前面
b.将接口的全类名写入到<mapper>,让mybatis知道sql语句此时是存储在接口中的。

注意:注解和XML都支持批量引入

 <mappers>
         <!--以下可以将com.itt.mapper包中的注解接口和xml            
       全部一次性引入-->
        <package name="com.itt.mapper"/>
 </mappers>

3.增删改的返回问题

  • 返回值 可以是void ,Integer,Long,Boolean,只需要在接口中改返回值就可以了!

4.事务提交方式

  • 手动提交:
SqlSession session = sessionFactory.openSession();
session.commit();//执行完commit时,手动提交 事务
  • 自动提交 :每一个dml语句自动提交
SqlSession session = sessionFactory.openSession(true);

5.参数问题

  • 目前将多个参数封装到一个javabean对象(pojo),然后使用该对象传递

  • a.传入多个参数时,不用在mapper.xml中编写parameterType

    异常提示:

  • stuNo不能使用,使用的是:【arg3,arg2,arg1,arg0,param3,param2,param1】

    <insert id="insertEmpInfo">
            insert into empinfo(id,name,age,job,phone)
            values (#{arg0},#{arg1},#{arg2},#{arg3},#{arg4})
        </insert>
    
  • b. 命名参数的方式

    可以在接口中通过@Param("")来指定sql中参数的名字

    void insertEmpInfo(@Param("sId") String id,
                           @Param("sName")  String name,
                           @Param("sAge") String age,
                           @Param("sJob") String job,
                           @Param("sPhone") String phone);
    
    <insert id="insertEmpInfo">
            insert into empinfo(id,name,age,job,phone)
            values (#{sId},#{sName},#{sAge},#{sJob},#{sPhone})
        </insert>
    
  • c. 综合使用的情况

    //一个是简单类型 ,一个是对象类型
    void insertEmpInfo(@Param("sId") String id,@Param("empInfo")  EmpInfo empInfo);
    
    <insert id="insertEmpInfo">
        insert into empinfo(id,name,age,job,phone)
        values (#{sId},#{empInfo.name},#{empInfo.age},#{empInfo.job},#{empInfo.phone})
    </insert>
    

6.增加null

  • oracle:如果插入的 字段是null,提示错误:Other 而不是gnull

  • mysql:如果插入的字段是null,可以正常执行(没有约束)

  • 原因:

  • 各个数据库在Mybatis中对各种数据类型的默认值不一致。

​mybatis中,jdbcTypeForNull(如果是null),则默认值OTHER。

在mysql中,mybatis将Other当做NULL来处理了,但是oracle不行。

解决:

oracle:null -> OTHER 手工告诉oracle:other -> null

a. 当某个数据类型oracle无法处理进,告诉它用默认值null 来处理

//使用#{empInfo.name,jdbcType=null}这个就可以了
<insert id="insertEmpInfo">
    insert into empinfo(id,name,age,job,phone)
    values (#{sId},#{empInfo.name,jdbcType=null},#{empInfo.age},#{empInfo.job},#{empInfo.phone})
</insert>

b. 配置mybatis全局配置文件conf.xml

<settings>
    <setting name="jdbcTypeForNull" value="NUll"/>
</settings>

7.返回值为HashMap的情况

  • 注意:在mysql中@MapKey("id")字段为小写
  • 在oracle中为全大写
  • map:
    • key:id value:Student
  • 程序根据select的返回值,知道map的value就是EmpInfo,根据@MapKey("id")知道Map的key是id
@MapKey("id")
HashMap<String,EmpInfo> queryAllEmp();
<select id="queryAllEmp" resultType="HashMap">
    select * from empinfo
</select>

8.ResultMap:字段和属性名的相应

  • column指的是数据库中的列名
  • property指的是类中的名字
<select id="queryAllEmpins" resultType="HashMap"
            resultMap="EmpInoMap">
        select * from empinfo
    </select>
    <resultMap id="EmpInoMap" type="empInfo">
        <id column="eid" property="id"/>
        <result column="ename" property="name"/>
        <result column="eage" property="age"/>
        <result column="ejob" property="job"/>
        <result column="ephone" property="phone"/>
    </resultMap>

9.别名问题

<!--设置单个/多个别名-->
    <typeAliases>
        <!--单个别名(别名 忽略大小写)-->
        <!--<typeAlias type="com.itt.entity.Student" alias="student"/>-->
        <!--批量定义别名,以下会自动将该包中的所有类 批量定义别名:别名就是类名(不带包名的类名)-->
        <package name="com.itt.entity"/>
    </typeAliases>
  • 当这个包下的子包 与Student重名时,必须使用注解的方式重新命名
@Alias("myempinfo")
public class EmpInfo {
    
}

10.处理where子句后面的and的三种方式

  • trim标签可以去掉后面的 and
  • <trim>可以处理拼接sql中【开头或结尾】第一个and
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo where
    <trim>
      <if test="id != null and id != 0">
          id = #{id} and 
      </if>
      <if test="name != null and name != ''">
          name like '%${name}%' and
      </if>
      <if test="phone != null and phone != ''">
          phone = #{phone} and 
      </if>
    </trim>
</select>
  • prefix="where":在整个语句中加where
  • prefix="set":在整个语句中加set,可用于更新
  • prefixOverrides="and":智能处理前面的and
  • suffixOverrides="and":智能处理后面的and
  • suffixOverrides=",":智能处理后面的,常用于更新
<trim prefix="where" prefixOverrides="and">
          <if test="id != null and id != 0">
              and id = #{id}
          </if>
          <if test="name != null and name != ''">
              and name like '%${name}%'
          </if>
          <if test="phone != null and phone != ''">
              and phone = #{phone}
          </if>
 </trim>
  • <where>标签可以去掉前面的and
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo
  <where>
      <if test="id != null and id != 0">
          and id = #{id}
      </if>
      <if test="name != null and name != ''">
          and name like '%${name}%'
      </if>
      <if test="phone != null and phone != ''">
          and phone = #{phone}
      </if>
  </where>
</select>
  • 直接 在where后面加:1 = 1
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo where 1 = 1
      <if test="id != null and id != 0">
          and id = #{id}
      </if>
      <if test="name != null and name != ''">
          and name like '%${name}%'
      </if>
      <if test="phone != null and phone != ''">
          and phone = #{phone}
      </if>
</select>

11.内置参数

  • _paramter:代表Mybatis的输入参数
<select id="queryByINP" parameterType="EmpInfo" resultType="EmpInfo">
  select * from empinfo
    <trim prefix="where" prefixOverrides="and">
      <if test="id != null and id != 0">
          and id = #{id}
      </if>
      <if test="name != null and name != ''">
          and ename like '%${name}%'
      </if>
      //_parameter替代parameterType这个输入的对象
      <if test="_parameter.phone != null and _parameter.phone != ''">
          and phone = #{_parameter.phone}
      </if>
    </trim>
</select>
  • _databaseId:代表当前数据库的名字

12.模糊查询三种方式

12.1

  • ${}原样输出
stuName like '%${stuName}%'
  • {}自动拼接' ':可以防止SQL注入

12.2 传值时,直接 传 %x%

student.setStuName("%s%");
stuName like #{stuName}

12.3 bind参数

<bind name="_queryName" value="'%'+name+'%'"/>
    <if test="name != null and name != ''">
         and name like #{_queryName}
    </if>
I:\MyBatisIdea\MyBatisGenerator\src\main\java

13.逆向工程

1.导入依赖

2.xml模板文件(修改生成路径、表名)

3.根据java模板类一键生成

  • 根据学生表->学生类、学生Mapper接口、studentMapper.xml

4.如何使用

​ * 增加Mybatis配置文件 conf.xml

  • 对于like模糊查询,逆向工程需要在传值时 写入%x%

逆向工程的实例:使用的是StudentExample

  • 测试类
@Test
    public  void queryAllEmpById() throws Exception{
        //Connection - SqlSession操作myBatis

        //config.xml  -> reader
        Reader reader = Resources.getResourceAsReader("conf.xml");

        //reader  ->SqlSession
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sessionFactory.openSession();

        StudentMapper mapper = session.getMapper(StudentMapper.class);

        StudentExample example = new StudentExample();
        StudentExample.Criteria criteria = example.createCriteria();
        criteria.andStunameLike("%d%");



        StudentExample example1 = new StudentExample();
        StudentExample.Criteria criteria1 = example1.createCriteria();
        //模糊查询
        criteria1.andStunoEqualTo(10);
        criteria1.andStunameLike("%k%");

        //使用exampl整合的方式实现or操作
        example.or(criteria1);
        //Example中的Criteria:为查询的条件
        List<Student> students = mapper.selectByExample(example);

        System.out.println(students);


        session.close();
    }

14.MyBatis架构和源码解析

  • Mybatis源码的几个主要部件

MyBatis中步骤:

  • 1.获取SqlSessionFactory对象
  • 2.获取SqlSession对象
  • 3.获取xxxMapper对象(代理接口 中的方法、mapper.xml中的<select>标签)
  • 4.执行标签中定义的SQL语句

1.获取SqlSessionFactory对象

  • parse解析器
    • 通过Configuration标签设置了properties、typeAliases、environments等
  • Mybatis将所有的配置信息存放到了Configuration configuration对象中
    • mapperElement的过程
  • <select id="",resultType="",parameterType="">等属性是通过
    parseStatementNode()这个方法解析的


  • Mybatis会将xxxMapper.xml文件解析成MappedStatement对象
  • 即parseStatementNode对象就是xxxMapper文件中的标签

  • MapperStatement -》存在于Configuration中

  • environment -》存在于Configuration中

  • 所有的配置信息、增删改标签全部存在于Configuration中

    结论:
    SqlSessionFactory对象—》DefaultSqlSessionFactory—》Configuration—》所有的配置信息

2.获取SqlSession对象(Executor为执行器)

  • configuration.newExecutor(tx, execType);-》默认类型为simpleExecutor
  • 并且根据不同的类型execType,产生不同的Executor,并对执行器进行拦截操作:
executor = (Executor) interceptorChain.pluginAll(executor);
  • 作用:以后如果我们要给MyBatis写自己的插件,就可以通过拦截器实现:

  • 下图就是使用拦截器一次次增强执行器Executor,从而使Executor有更强大的功能!

  • 返回的是:
    DefaultSqlSession(configuration, executor, 事务问题);

  • SqlSession ->openSession()--->openSessionFromDataSource() -->DefaultSqlSession对象

  • 执行的流程
  • SqlSession -> DefaultSqlSession对象 -> 执行SQL

  • 插件开发:
    1.写插件
    2.把插件放入到拦截器中

  • 插件

select * from student --》拦截器

目标对象target的包装后的产物 --->metaObject.getValue("可以从target中获取")

通过打印语句,可知,target就是 RoutingStatementHandler

----------》

metaObject.getValue("可以从RoutingStatementHandler中获取")

可以从RoutingStatementHandler获得:getBoundSql,getParameterHandler

------->--->metaObject.getValue("parameterHandler")

  • metaObject.getValue("parameterHandler.parameterObject")//xxxMapper.xml中的语句中的参数值
  • metaObject.getValue("parameterHandler.boundSql")//xxxMapper.xml中sql的语句

3.获取xxxMapper对象(代理接口 中的方法、mapper.xml中的<select>标签)

4.执行标签中定义的SQL语句

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

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,498评论 0 4
  • 前言 接着上一篇Mybatis入门继续,上一篇主要演示了Mybatis的基本操作,对数据库的增删改查,但是在实际项...
    Real_man阅读 1,547评论 0 2
  • 对象之间的关系: 关联关系:A对象依赖B对象,并且把B对象作为A对象的一个属性,则A和B是依赖关系. ** 按照多...
    CoderZS阅读 631评论 0 8
  • 前言 MyBatis是一个优秀的持久层ORM框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL...
    AI乔治阅读 639评论 0 5
  • 今天终于可以去上班了,还有一堆事儿等着处理,于是早早来到了学校。 看到张雪老师分身乏力于是就帮他就帮他...
    海博乔森教育孙老师阅读 46评论 0 0