MyBatis入门

作者: onlyHalfSoul | 来源:发表于2018-05-25 15:18 被阅读313次

    MyBatis主要组成部分

    clipboard.png
    1. SqlSessionFactoryBuilder(构造器)

    根据配置信息或代码生成SqlSessionFactory接口

    2. SqlSessionFactory(工厂接口)

    依靠工厂来生成SQLSesson(会话)

    3. SqlSession(sql处理器)

    既可以发送SQL去执行并返回结果,也可以获取Mapper的接口

    4. SQL Mqapper(映射规则及SQL定义)

    MyBatis的新设计组件,由Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则。负责发送SQL去执行。并返回结果。

    SqlSessionFactory

    MyBatis的应用都是以SqlSessionFactory的实例为中心。SqlSessionFactory的实例是由SqlSessionFactoryBuilder生成的。

    注:SqlSessionFactory是一个工厂接口,不是实现类

    SqlSessionFactory的任务是创建SQLSession。SQLSession类似于JDBC的Connection对象。

    可用XML配置和代码方式创建SQLSessionFactory,推荐使用XML配置方法

    SQLSession

    SqlSession是一个接口类,相当于前台,主要和程序员交接,调用Executor接口执行相应操作。SqlSession在中间负责接收功能参数,之后返回结果(是一个黑箱操作)

    SQLSession类似于JDBC中的Connection对象,需要及时关闭

    SQLSession的执行包括两种方法:1.获取映射器,让映射器通过命名空间和方法名称找到对应的SQL,发送到数据库并执行。2.直接通过命名信息去执行SQL并返回结果。在SQLSession层可以通过update,insert,select,delete等方法,带上SQL的id来操作在XML中配置的SQL,进而完成工作。也支持事物,通过commit和rollback方法提交或者回滚事物。


    clipboa1rd.png

    映射器 (XML Mapper和Java接口)

    映射器是由Java接口和XML文件(或注解)组成,作用是:

    • 定义参数类型。
    • 描述缓存。
    • 描述SQL语句。
    • 定义查询结果和POJO的映射关系。

    映射器有两种实现方式,1. xml文件描述。2. java代码实现,添加注解方式。

    建议使用xml方式

    MyBatis生命周期

    SQLSessionFactoryBuilder

    利用xml配置文件或java编码构建SQLSessionFactory,可构建多个SQLSessionFactory。它是一个构建器,一旦构建出SQLSessionFactory,它的作用就完成了。只存在于方法的局部,作用就是生产SQLSessionFactory。

    SQLSessionFactory

    SQLSessionFactory的作用是创建SQLSession,每次访问数据库都需要它来创建SQLSession,所以SQLSessionFactory存在于MyBatis的整个生命周期。

    通常一个数据库对应一个SQLSessionFactory,避免消耗过多的数据库连接资源。

    SQLSession

    SQLSession是一个会话,它的生命周期是在请求数据库处理事务的过程当中,相当于JDBC的Connection对象,属于==线程不安全对象==,在涉及多线程时需格外注意,操作数据库需要注意其隔离级别,数据库锁等高级特性。创建并使用完SQLSession后必须及时

    关闭,减少资源占用。

    Mapper

    Mapper是一个接口,没有任何实现类,作用是发送SQL,再返回需要的结果或执行SQL修改数据库的数据。 它是在一个SQLSession事物的方法中使用的,然后废弃。

    Mybatis设置

    <?xml version = "1.0" encoding = "UTF-8"?>
    <configuration><!--配置-->
        <properties/><!--属性-->
        <settings/><!--设置-->
        <typeAliases/><!--类型命名-->
        <typeHandlers/><!--类型处理器-->
        <objectFactory/><!--对象工厂-->
        <plugins/><!--插件-->
        <environments><!--配置环境-->
            <environment><!--环境变量-->
                <transactionManager/><!--事物管理器-->
                <dataSource/><!--数据源-->
            </environment>
        </environments>
        <databaseIdProvider/><!--数据库厂商标识-->
        <mappers/><!--映射器-->
    </configeration>    
        
    

    properties元素

    properties是个配置属性的元素,配置文件的上下文中使用。

    三种配置方式

    1. property子元素
    2. properties配置文件
    3. 程序参数配置

    property子元素

    property子元素配置代码如下:

    <properties>
        <property name = "dirver" value = "com.mysql.jdbc.Dirver"/>
        <property name = "url" value = "jdbc:mysql://localhost:3306/mybatis"/>
        <property name = "username" value = "root"/>
        <property name = "password" value = "123"/>
    </properties>
    

    这样我们就可以在上下文中使用配置好的properties属性值。

    <dataSourse type = "POOLED">
        <property name = "dirver" value = "${dirver}"/>
        <property name = "url" value = "${url}"/>
        <property name = "username" value = "${username}"/>
        <property name = "password" value = "${password}"/>
    </dataSourse>
    

    properties配置文件

    使用properties配置文件可让多个配置文件重复使用

    <!--jdbc.properties-->
    dirver = com.mysql.jdbc.Dirver
    url = jdbc:mysql://localhost:3306/mybatis
    username = root
    password = 123
    
    

    引用变量代码如下:

    <properties resource = "jdbc.properties"/>
    

    程序参数传递

    在实际对于用户名密码需要进行加密处理,则需要让jdbc.properties中的username和password两个属性使用加密字符串,需要在生产SQLSessionFactory之前转化为明文,使用系统提供的decode(str)方法解密。使用代码方式创建SQLSessionFactory:

    InputStream cfgStream = null;
    reader cdgReader = null;
    InputStream proStream = null;
    Reader proReader = null;
    Properties properties = null;
    try{
        //读入配置文件流
        cfgStream = Resources.getResourceAsStream("MyBatis-config.xml");
        cfgReader = new InputStreamReader(cfgStream);
        //读入属性文件
        proStream = Resources.getResourceAsStream("jdbc.properties");
        proReader = new InputStreamReader(proStream);
        properties = new Properties();
        properties.load(proReader);
        //解密为明文
        properties.setProperty("username",decode(properties.getProperty("username")));
        properties.setProperty("password",decode(properties.getProperty("password")));
    }catch (IOException ex){
        Logger.getLogger(SqlSessionFactoryUtil.class.getName()).log(Level.SERVRE,null,ex);
    }
    sysnchronized(CLASS_LOCK){
        if(sqlSessionFactory == null){
            //使用属性来创建SQLSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().builder(cfgReader,properties);
        }
    }
    
    

    三种配置优先级

    通过方法传递 > 读取properties文件 > property直接指定

    三种方法不要混合使用,容易造成管理混乱。
    优先使用读取properties文件方式。

    设置

    设置(setting)是MyBatis最复杂的一块配置,也是最重要的配置块之一。
    它会改变MyBatis的运行行为,但是即使不配置setting,MyBatis也能正常使用。
    完整的setting配置如下:

    <settings>
        <setting name = "cacheEnabled" value = "true"/>
        <setting name = "lazyLoadingEnabled" value = "true"/>
        <setting name = "multipleResultSetsEnabled" value = "true"/>
        <setting name = "useColumnLabel" value = "true"/>
        <setting name = "useGenerateKeys" value = "false"/>
        <setting name = "autoMappingBehavior" value = "PARTIAL"/>
        <setting name = "defaultExcutorType" value = "SIMPLE"/>
        <setting name = "defaultStatementTimeout" value = "25"/>
        <setting name = "safeRowBoundsEnabled" value = "false"/>
        <setting name = "mapUnderscoreToCamelCase" value = "false"/>
        <setting name = "localCacheScope" value = "SESSION"/>
        <setting name = "jdbcTypeForNull" value = "OTHER"/>
        <setting name = "lazyLoadTriggerMethods" value = "equals,clone,hashCode,toString"/>
    </settings>
    

    大多时候不必配置他们,或只需配置少数几项。

    别名

    别名(typeAliases)是一个指代名称,当遇到类全限定名过长时,我们使用typeAliases去代替它。这个名称在MyBatis上下文中使用。别名在MyBatis中分为系统定义别名和自定义别名两类。

    别名不区分大小写。

    一个typeAliases的实例是在解析配置文件时生成的,然后长期保存在configuration对象中,当我们使用时就不必再次运行生成实例了。

    系统自定义别名

    MyBatis系统定义了一些经常使用的类型的别名,例如:数值,字符串,日期集合等,可以在MyBatis中直接调用,不要重复定义把他们覆盖。

    自定义别名

    MyBatis允许自定义别名,代码例如:

    <!--自定义别名-->
    <typeAliases>
        <typeAlias alias = "role" type = "com.learn.chapter2.po.Role"/>
    </typeAliases>
    

    当自定义别名过多时,可以定义自动扫描包的范围,并在需要定义的类的上方加注解即可批量定义别名。

    <!--扫描包,批量定义别名-->
    <typeAliases>
        <package name = "com.learn.chapter2.po"/>
        <package name = "com.learn.chapter3.po"/>
    </typeAliases>
    
    /*
    *别名注解
    */
    @Alias("role")
    public class Role{
        //some code
    }
    

    不加注解也能加载别名,默认将类名第一个字母变为小写,故一定要避免重名。

    typeHandler类型处理器

    MyBatis在预处理语句(prepareStatment)中设置一个参数,或从结果集(ResultSet)中取出一个值时,都会用注册了的typeHandler进行处理。

    由于数据库的厂商不同,不同的厂商设置的参数可能不同,数据库也可以自定义数据类型,typeHandler允许根据项目的需要自定义设置java传递到数据库的参数中,或者从数据库读出数据,也需要进行特殊处理,这些都是在自定义typeHandler中处理,尤其是枚举类型常常需要使用typeHandler来进行转换。

    typeHandler分为系统定义和自定义两种,一般系统定义可满足绝大部分功能。自定义typeHandler务必小心谨慎。

    typeHandler常用配置为javaType和jdbcType,作用是将JavaType转化为jdbcType,或者将数据库取出结果从jdbcType转化为JavaType。

    .......

    ObjectFactory

    mybatis在构建一个结果返回的时候,需要用到ObjectFactory(对象工厂)去构建POJO,在MyBatis中也可以定制自己的对象工厂。一般使用默认的ObjectFactory即可。

    自定义ObjectFactory需要进行配置

    <objectFactory type="com.learn.chapter3.objectFactory.MyObjectFactory">
        <property name="name" value="MyObjectFactory" />
    </objectFactory>
    

    自定义ObjectFactory需要刷新ObjectFactory接口,而系统自带的DefaultObjectfactory已经实现了ObjectFactory接口,故只需让myObjectFactory基础DefaultObjectFactory即可。实例如下:

    
    //MyObjectFactory
    packgae com.learn.chapter3.objectFactory;
    improt java util.List;
    import java.util.Properties;
    import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
    import org.apache.log4j.Logger;
    
    public class MyObjectFactory extends DefaultObjectFactory{
        
        private static final long serialVerSionUID = -381482721604028629L;
        Logger log = Logger.getLogger(MyobjectFactory.class);
        
        @Override
        public void setProperties(Properties prprty){
            log.info("定制属性:"+prprty);
            super.setProperties(prprts);
        }
        
        @Override
        public <T> T create(Class<T> type){
            log.info("使用定制对象工厂的create的方法构建单个对象");
            return super.create(type);
        }
        
        @Override
        public <T> T create(Class<T> type, List<Class<?>> list, List<Objetc> list1){
            log.info("使用定制对象工厂的create方法构建列表对象");
            return super.create(type,list,list1);
        }
        
        @Override
        public <T> boolean isCollection(Class<T> type){
            return super.isCollection(type);
        }
        
    }
    
    

    插件

    比较复杂,会出现一些覆盖MyBatis内部核心的行为。

    environment配置环境

    注册数据源

    配置环境可以注册多个数据源(dataSource),每个数据源需要进行数据库源配置及数据库事物(transactionManager)配置。

    连接池数据配置示例:

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="autoCommit" value="false"/>
            </transactionManager>
            <dataSource type="POOLED">
                <property name="dirver" value="com.mysql.jdbc.Dirver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/oa"/>
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            </dataSource>
        </environment>
    </environments>
    

    上述代码中environments中default属性,标明在缺省情况下启用哪个数据源。

    • environment元素是配置一个数据源的,属性id是设置这个数据源的标识,以方便mybatis在上下文中使用它。
    • transactionManager配置数据源的数据库事物,其中type属性有三种配置方式。
    1. JDBC,采用JDBC方式管理事物,在独立编码中常常使用。
    2. MANAGED,采用容器的方式管理事物,在JNDI数据源中使用。
    3. 自定义,由使用者自定义数据库事物管理办法,适用于特殊应用。
    • property元素可以配置数据源各类属性,这里的autoCommit=false,则是要求数据源不自动提交。
    • dataSource标签配置的是数据源的连接信息,type属性提供数据库的连接方式的配置,在mybatis中有几种连接方式:
    1. UNPOOLED,非连接池数据库。
    2. POOLED,连接池数据库
    3. JNDI,JNDI数据源。
    4. 自定义数据源。
      其中property元素是定义数据库连接的各类参数。

    数据库事物

    数据库事务Mybatis交由SqlSession控制,可以通过SqlSession提交(commit)或者回滚(rollback)。插入一个角色对象,如果成功就提交,否则就回滚。

    try{
        sqlSession = SqlSessionFactoryUtil.openSqlSession();
        RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
        int count = roleMapper.insertRole(role);
        sqlSession.commit();
        return count;
    }catch(Exception ex){
        sqlSession.rollback();
    }finally{
        sqlSession.close();
    }
    

    大部分时候都是用Spring框架控制数据库事物

    dataSourceIdProvider数据库厂商标识

    可选择使用系统默认规则和不使用系统默认规则。

    引入映射器的方法

    映射器是mybatis最复杂,最核心的组件。

    • 首先定义映射器接口
    package com.learn.chapter3.mapper;
    import java.util.List;
    import com.learn.chapter3.po.Role;
    public interface RoleMapper {
        public Role getRole(Long id);
    }
    
    • 其次给出xml文件
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.learn.chapter3.mapper.RoleMapper">
    <select id="getRole" paramenterType="long" resultType="com.learn.chapter3.po.Role">
        select id,role_name as roleName, note from t_role where id=#{id}
    </select>
    </mapper>
    

    引入映射器的常用方法:

    1. 用文件路径引入映射器
    <mappers>
        <mapper resource="com/learn/chapter3/mapper/roleMapper.xml"/>
    </mappers>
    
    
    1. 用包名映入映射器
    <mappers>
        <package name="com.learn.chapter3.mapper"/>
    </mappers>
    
    
    1. 用类注册引入映射器
    <mappers>
        <mapper class="com.learn.chapter3.mapper.UserMapper"/>
        <mapper class="com.learn.chapter3.mapper.RoleMapper"/>
    </mappers>
    
    
    1. 用userMapper.xml引入映射器
    <mappers>
        <mapper url="file:///var/mappers/com/learn/chapter3/mapper/roleMapper/xml"/>
        <mapper url="file:///var/mappers/com/learn/chapter3/mapper/RoleMapper.xml"/>
    </mappers>
    
    

    映射器

    MyBatis是针对映射器构造的SQL构建的轻量级框架,并且通过配置生成对应的JavaBean返回给调用者,这些配置主要便是映射器。

    映射器的主要元素

    • select ,查询语句,最常用最复杂的元素。可以自定义参数,返回结果集等
    • insert, 插入语句。执行后返回一个整数,代表插入的条数。
    • update,更新语句。执行后返回一个整数,代表更新的条数。
    • delete,删除语句。执行后返回一个整数,代表删除的条数。
    • parameterMap,定义参数映射关系。即将被删除的元素,不建议使用。
    • sql, 允许定义一部分的SQL,然后可在各个地方引用它。
    • resultMap, 用来描述从数据库中结果集中来加载对象,最复杂,最强大的元素。
    • cache,给命名空间缓存配置。
    • cache-ref,其他命名空间缓存配置引用。

    select

    简单select数据类型的例子

    <select id="countFirstName" parameterType="String" resultType="int">
        select count(*) as total from t_user where name like concat(#{firstName},'%')
    </select>
    

    在Dao接口中定义方法

    public int countFirstName(String firstName);
    
    • id 标出了这条sql
    • paramenterType 定义参数类型
    • resultType定义了返回值类型

    自动映射

    setting元素中有autoMappingBehavior参数,当它不设置为NONE时,MyBatis会设置自动映射功能。只要返回的Sql的列名和javaBean的属性一致,mybatis会帮我们回填这些字段,无需任何配置。

    注:数据库规范单词间用下划线分隔,java中使用驼峰式命名,可以使用列的别名使mybatis自动映射,也可以直接配置文件中开启驼峰式命名方式。

    传递多个参数

    使用map传递多个参数

    使用Map接口作为参数实现多参数传递

    <select id="findRoleByMap" parameterType="map" resultMap="roleMap">
        select id, role_name, note 
        from t_role
        where role_name like concat('%',#{roleName},'%')
        and note like concat('%',#{note},'%')
    </select>
    

    RoleDao接口:

    public List<Role> findRoleByMap(Map<String,String> params);
    

    参数传递代码如下:

    Map<String,String> paramsMap = new HashMap<String,String>();
        paramsMap.put("roleName", "me");
        paramsMap.Put("note","te");
    role 
    
    clipbo32ard.png

    相关文章

      网友评论

        本文标题:MyBatis入门

        本文链接:https://www.haomeiwen.com/subject/iyqujftx.html