Mybatis进阶

1.数据库的环境切换

2.注解方式

​## 推荐使用xml

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

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

 
         
        
 

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 into empinfo(id,name,age,job,phone)
            values (#{arg0},#{arg1},#{arg2},#{arg3},#{arg4})
        
    
  • 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 into empinfo(id,name,age,job,phone)
            values (#{sId},#{sName},#{sAge},#{sJob},#{sPhone})
        
    
  • c. 综合使用的情况

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

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 into empinfo(id,name,age,job,phone)
    values (#{sId},#{empInfo.name,jdbcType=null},#{empInfo.age},#{empInfo.job},#{empInfo.phone})

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


    

7.返回值为HashMap的情况

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

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

  • column指的是数据库中的列名
  • property指的是类中的名字

    
        
        
        
        
        
    

9.别名问题


    
        
        
        
        
    
  • 当这个包下的子包 与Student重名时,必须使用注解的方式重新命名
@Alias("myempinfo")
public class EmpInfo {
    
}

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

  • trim标签可以去掉后面的 and
  • 可以处理拼接sql中【开头或结尾】第一个and

  • prefix="where":在整个语句中加where
  • prefix="set":在整个语句中加set,可用于更新
  • prefixOverrides="and":智能处理前面的and
  • suffixOverrides="and":智能处理后面的and
  • suffixOverrides=",":智能处理后面的,常用于更新

          
              and id = #{id}
          
          
              and name like '%${name}%'
          
          
              and phone = #{phone}
          
 
  • 标签可以去掉前面的and

  • 直接 在where后面加:1 = 1

11.内置参数

  • _paramter:代表Mybatis的输入参数

  • _databaseId:代表当前数据库的名字

12.模糊查询三种方式

12.1

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

12.2 传值时,直接 传 %x%

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

12.3 bind参数


    
         and name like #{_queryName}
    
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 students = mapper.selectByExample(example);

        System.out.println(students);


        session.close();
    }

14.MyBatis架构和源码解析

  • Mybatis源码的几个主要部件

MyBatis中步骤:

  • 1.获取SqlSessionFactory对象
  • 2.获取SqlSession对象
  • 3.获取xxxMapper对象(代理接口 中的方法、mapper.xml中的等属性是通过
    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中的