深入浅出Mybatis系列(二)Mybatis核心配置篇

在本篇中小编主要对SqlSession及Configuration重点介绍,这两块知识点可以说是Mybatis中最重要的知识点,只有对
SqlSession和Configuration有清醒的认识后,学习效率就翻倍提升。以下所有知识点都是小编所学所悟。如有问题,请留言评论指出,欢迎讨论,一起学习。

如图所示,在Mybatis的架构设计中,最重要的两块就是SqlSession,和Configuration。

关键词

①SqlSession ②Configuration

概念介绍

  • SqlSession
  • Configuration

SqlSession

Session是会话的意思,SqlSession名字就说明了这是一个Sql的会话。
单是从代码上来看,它就是负责和数据库操作的一个抽象接口。但是从概念上来说,就是类似于JDBC中的Connection。SqlSession它的底层封装了JDBC连接,可以用SqlSession实例来直接执行被映射的SQL语句.每个线程都应该有它自己的SqlSession实例.SqlSession的实例不能被共享
不过Mybatis的SqlSession比JDBC更加强大,能提供对象关系映射(ORM)的能力。同时也支持占位符,和动态Sql(容易出现sql注入问题,要注意)。

传统JDBC方式

比较繁琐要导入驱动,获取连接,要自己拼装sql。关闭连接。
但是比较快,因为不论是Mybatis还是Hibernate都是对原生JDBC的封装。

public class JdbcTest {

    static {
        try {//注册驱动,反射方式加载
            Class.forName("com.mysql.jdbc.Driver");
        }catch (Exception e){
        }
    }

    @Test
    public void jdbcTest()throws Exception{
        String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
        //设置用户名
        String username = "root";
        //设置密码
        String password = "root";
        //获得连接对象
        Connection con = DriverManager.getConnection(url, username, password);
        //获得执行者对象
        String sql = "select * from t_user where id = ?";
        PreparedStatement ps = con.prepareStatement(sql);
        ps.setInt(1,2);
        //获得结果集
        ResultSet rs = ps.executeQuery();
        //结果集处理,
        while(rs.next()){
            System.out.println(rs.getString("id")+"  "+rs.getString("name"));
        }
        //释放资源
        rs.close();
        ps.close();
        con.close();
    }
}

Mybatis方式

能提供对象关系映射(ORM)的能力。通过代理的方式,实现我们的Mapper接口层和xml配置文件的绑定,实现通过对象实例,操作数据库。(本篇不细讲,会在《深入浅出Mybatis系列(四)Mapper方法代理篇》主要做讲解)

 @Test
  public void dynamicTest() {
    //读取配置信息
    InputStream mapperInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml");
    //生成SqlSession工厂
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(mapperInputStream, "development");
    //获取Mybatis配置信息
    Configuration configuration = sqlSessionFactory.getConfiguration();
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    //获取Mapper
    TUserMapper mapper = configuration.getMapperRegistry().getMapper(TUserMapper.class, sqlSession);
    TUser tUser = mapper.selectOne(1);
    System.out.println(tUser);
}

另外SqlSession还提供批处理的能力,和事务的能力。
什么场景用到批处理呢?
当要处理一批sql的时候,如果是一个sql一个sql的执行,那么每一条sql的执行都会有一次网络传输的过程,将sql从本台服务器发送到数据库服务器中。那么这种情况就时候就适合使用。原理就是通过BatchExecutor批处理执行器处理,将要批处理的sql,一次发送到数据库服务器来执行。

 /**
   * 批处理测试
   */
  @Test
  public void batchTest() {
    InputStream mapperInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(mapperInputStream);
    //设置执行类型为批处理ExecutorType.BATCH,
    SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
    TUserMapper mapper = batchSqlSession.getMapper(TUserMapper.class);
    //mapper批处理操作
    
    
    //成功提交...
    batchSqlSession.commit();
    //失败回滚
    batchSqlSession.rollback();
  }

说道SqlSession一起把动态sql,和Sql注入问题给说一下。

什么是动态Sql?

所谓动态Sql就是Sql可以不直接写死,而是通过参数的方式,动态的去拼装Sql。
那这个时候就会用到两个技术。

  1. #{} 占位符
  2. ${} 变量符

eg:

  1. select id, name from T_USER where name = #{name}

这个时候用到的是占位符,name = “中国”。对于占位符MyBatis不直接处理而是交个JDBC来处理,利用PreparedStatement来设置动态参数,PreparedStatement可以预编译sql,可以sql缓存,同时可以有效防止sql注入。

    String sql = "select * from t_user where name = ?";
    PreparedStatement ps = con.prepareStatement(sql);
    ps.setString(1,"中国");
  1. 如果换成变量符
    select id, name from T_USER where name = ${name}

这个时候,因为是变量符,Mybatis会直接处理生成Sql,入参是什么就拼装成什么,此时name就只是一个变量,可以被赋任何值,正常情况,不会出现问题,但是遇到恶意情况,当参数等于 name = "‘中国1’ or 1 = 1,此时一定就会查到,因为就变成or操作1永远等于1,这就是利用Mybatis动态生成Sql的特征,来注入恶意的sql。

这里注意一个知识点,$变量符,是由Mybatis实现的,#占位符是由JDBC原生实现的。

Configuration

从上面介绍SqlSession的例子中能看到很多都是从Configuration中获取的信息,其实Configuration就是将配置文件转换成Java类。Mybatis中的一切都是从Configuration中来的,
包括TypeHandlerRegistry类型注册器,拦截器InterceptorChain,别名注册器TypeAliasRegistry,Mapper注册器 MapperRegistry

上面所指出的类,都是核心处理的。从起名就能看出来他是干啥的。
比如

  1. TypeHandlerRegistry
    每个类型指定类型转换器。
 register(Boolean.class, new BooleanTypeHandler());
 register(boolean.class, new BooleanTypeHandler());
 register(JdbcType.BOOLEAN, new BooleanTypeHandler());
 register(JdbcType.BIT, new BooleanTypeHandler());
  1. InterceptorChain 就是一个拦截链,主要用做插件使用,最简单的例子就是分页插件(pagehelper),就是在sql上加上limit(实现类:PageInterceptor)。进行分页。(mysql和Oracle处理不一样)
  2. TypeAliasRegistry就是将Mybatis中的数据类型,与Java中的数据类型做一个转换,解析xml时候使用
  • "byte"<==> Byte.class
  • "_integer" <==> int.class
  • "int" <==> Integer.class
  1. MapperRegistry就更核心了,负责为Mapper接口层生成代理实现。这个比较重要,内容涉及要多,会在《深入浅出Mybatis系列(四)Mapper方法代理篇》主要讲解。主要讲xml如何与Mapper接口绑定,生成代理类。sql如何拼装,占位符#和变量符$底层实现。

MapperRegistry是非常核心的实现,主要实现对象关系的映射,将xml通过代理生成Mapper。这点要一定要注意下,看Mybatis源码最重要的就是要学这个。

SqlSession和Configuration是Mybatis中很重要的两个处理类,Configuration主要解析Mybatis的xml配置,保存Mapper代理,保存需要的配置信息,而SqlSession就只负责和数据库的交互。本篇使你对Mybatis有一个大概的认识,下一篇主要讲Mybatis如何解析xml配置信息,生成Configuration对象。

文章最后送你一个Mybatis的一个历史性错误
autoCommmit,
多写了一个m,由此可见,在nb的程序猿也有出错的时候,告诫大家,写代码时候一定要检查好拼写。

发布了234 篇原创文章 · 获赞 116 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/Message_lx/article/details/89532999