Mybatis相关知识(1)

Mybatis相关知识

1 Mybatis介绍
Mybatis 是一个==半 ORM(对象关系映射)==框架,它内部封装了 JDBC,开发时只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement 等繁杂的过程。程序员直接编写原生态 sql,可以严格控制 sql 执行性能,灵活度高

上面提到了半ORM框架,那么和全自动ORM框架区别在哪
答: 全自动ORM框架以Hibernate为例,Hibernate是全自动的ORM映射工具,使用Hibernate查询的关联对象或者关联集合对象时,根据对象关系模型直接获取
而Mybatis在查询关联对象或者关联集合对象时,需要手动编写SQL来完成,因此是半自动ORM的框架

Mybatis和Hibernate的适用场景:
Hibernate 是重量级框架,适合于需求相对稳定,中小型的项目
MyBatis 是轻量级框架,适合于需求变化频繁,大型的项目

2 Mybatis优势和劣势
优势:
基于SQL语句编程,灵活,不会对应用程序或者数据库的现有设计造成任何影响,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用
与JDBC相比,消除了JDBC大量冗余的代码不需要手动开关连接很好的与各种数据库兼容
提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护
能够与Spring和其他框架很好的集成

缺点
SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

后来,有更为强大的mybatis-plus,在此基础上做了增强,在开发中也得到了使用。

3 适用mybatis的步骤:
(1) 创建SqlSessionFactory
(2)通过SqlSessionFactory创建SqlSession
(3) sqlsession执行数据库操作
(4) session.commit()提交事务
(5) session.close()关闭会话

4 Mybatis的工作原理
第一步: 读取mybatis配置文件,mybatis-config.xml文件
第二步: mybatis-config.xml文件加载了项目程序的mapper文件,对应的xml文件。
第三步: 创建SqlSessionFactory
第四步: 通过SqlSessionFactory创建SqlSession
第五步: 执行器Executor
第六步: MapperedStatement对象
第七步: 输入参数类型,比如实体对象,基本数据类型等。
第八步: MapperedStatement对象将参数,执行数据库持久化操作,输出结果映射

下面将用一个案例配套步骤进行讲解:
首先,得建立一个数据库,我这里数据库是babytun,里面有几张表商品表,商品种类表等。对应的java实体类是Goods和Category。
好来看mybatis-config.xml文件里面配置的内容


DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <settings>
        
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    settings>

    
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <property name="helperDialect" value="mysql"/> 
            <property name="reasonable" value="true"/> 
        plugin>
    plugins>

    <environments default="dev"> 
        <environment id="dev"> 
            
            <transactionManager type="JDBC">transactionManager>
            
            
            
            <dataSource type="com.mybatis.datasource.C3p0DataSourceFactory">
                <property name="driverClass" value="com.mysql.jdbc.Driver"/>
                <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/babytun?"/>
                <property name="user" value="root"/>
                <property name="password" value="root"/>
                <property name="initialPoolSize" value="5"/>
                <property name="maxPoolSize" value="20"/>
                <property name="minPoolSize" value="5"/>
            dataSource>
        environment>
    environments>

    <mappers>
        <mapper resource="mappers/goods.xml"/>
    mappers>

configuration>

主要是配置实体类和数据库表驼峰转换,分页插件和数据源信息,mappers节点配置了对应Goods实体的xml文件即goods.xml。当然goods.xml就是操作和Goods相关的SQL。

来到第三步: 因为涉及创建会话,关闭会话,我们将这些方法封装到一个文件,方便调用。即文件MybatisUils.java。内容如下:

public class MybatisUils {
    //利用static保证SqlSessionFactory全局唯一;
    private static SqlSessionFactory sqlSessionFactory = null;
    //利用static块在初始化类时实例化sqlSessionFactory;
    static {
        Reader reader = null;
        try {
            reader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
            //初始化错误时,通过抛出异常通知调用者;
            throw new ExceptionInInitializerError(e);
        }
    }

    public static SqlSession openSession(){ //创建新的SqlSession对象;
        return sqlSessionFactory.openSession();
    }

    public static void CloseSession(SqlSession session){ //关闭SqlSession;
        if(session!=null){
            session.close();
        }
    }
}

此外,我们这里用的是c3p0数据源,这里创建了一个数据源工厂类C3p0DataSourceFactory

/*
c3p0和mybatis兼容使用的数据源工厂类;
 */
public class C3p0DataSourceFactory extends UnpooledDataSourceFactory {
    public C3p0DataSourceFactory(){
        this.dataSource = new ComboPooledDataSource();
    }

}

来到第五步和后续步骤:
需要写一个方法,用mybatis完成对数据库的查询。
首先,比如完成对数据库goods表的全部查询。

@Test
    public void testSelectAll(){
        SqlSession session = null;
        try {
            session = MybatisUils.openSession();
            List<Goods> list = session.selectList("goods.selectAll"); 
            //goods.xml中的namespace="goods" select id="selectAll"相对应;
            for(Goods good:list){
                System.out.println(good.getTitle());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            MybatisUils.CloseSession(session);
        }
    }

然后在goods.xml中写入对应的SQL,注意命名空间和方法保持一致。 id和后端的selectAll保持一致,而且在同一个xml文件中,方法id不要重名。 SQL语句如下,查询前十条商品按照id降序显示。 resultType就是上面的第八步,结果映射到实体。useCache表示是否适用缓存。 useCache=“false” 代表不使用缓存

<mapper namespace="goods">
 <select id="selectAll" resultType="com.mybatis.entity.Goods" useCache="false">
        select * from t_goods order by goods_id desc limit 10
    select>
mapper>

提到了缓存,mybatis有一级缓存和二级缓存。
一级缓存是SqlSession级别的缓存,默认开启
二级缓存是NameSpace级别(Mapper)的缓存,多个SqlSession可以共享,使用时需要进行配置开启。
缓存的查找顺序:二级缓存 => 一级缓存 => 数据库

从上面可以看到,二级缓存开启可以提高查询效率,减少数据库的访问次数,提高系统性能和响应速度。

怎么开启二级缓存呢?
这里可以在全局mybatis-config.xml配置,当然也可以在单个xml文件配置,例如,我这里在goods.xml配置。
在和 之间配置以下内容。一般放在SQL节点前。配置后的完整的goods.xml如下
相关参数,见下面的解释。

<mapper namespace="goods">
 <cache eviction="LRU" flushInterval="600000" size="512" readOnly="true"/> 
    
    
    <select id="selectAll" resultType="com.mybatis.entity.Goods" useCache="false">
        select * from t_goods order by goods_id desc limit 10
    select>
mapper>

当然此刻,想必有同学注意到上面八个步骤,第五步和第六步貌似没有讲,因为这是框架完成的,那接下来讲Executor和MapperedStatement对象。

Executor:是执行器。
Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor
SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象。
BatchExecutor:执行update没有select,将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。

那么Mybatis中如何指定使用哪一种Executor执行器呢?
在Mybatis配置文件中,可以指定默认的ExecutorType,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数,如SqlSession openSession(ExecutorType execType)。配置默认的执行器。SIMPLE 就是普通的执行器REUSE 执行器会重用预处理语句BATCH 执行器将重用语句并执行批量更新

MapperedStatement对象
Mybatis将所有Xml配置信息都封装到All-In-One对象Configuration内部。在Xml映射文件中,标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个select insert delete update 标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象

5 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的具体SQL语句的书写及其注意事项。

你可能感兴趣的:(java,mybatis,java)