美文网首页程序员
3.详解MyBatis的配置文件

3.详解MyBatis的配置文件

作者: 落叶飞逝的恋 | 来源:发表于2017-08-20 16:41 被阅读897次

    MyBatis配置xml层次结构,而且必须注意其顺序。

    <!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>
    

    MyBatis官网中文XML映射配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <!--配置-->
    <configuration>
        <!--属性-->
        <properties></properties>
        <!--设置-->
        <settings>
            <setting name="" value=""/>
        </settings>
        <!--类型命名-->
        <typeAliases></typeAliases>
        <!--类型处理器-->
        <typeHandlers></typeHandlers>
        <!--对象工厂-->
        <objectFactory type=""/>
        <!--插件-->
        <plugins>
            <plugin interceptor=""></plugin>
        </plugins>
        <!--配置环境-->
        <environments default="">
            <!--环境变量-->
            <environment id="">
                <!--事务管理器-->
                <transactionManager type=""></transactionManager>
                <!--数据源-->
                <dataSource type="">
                </dataSource>
            </environment>
        </environments>
        <!--数据库厂商标识-->
        <databaseIdProvider type=""/>
        <!--映射器-->
        <mappers></mappers>
    </configuration>
    

    1.properties属性

    properties是一个配置属性的元素,让我们能在配置文件的上下文中使用它。

    如果属性在不止一个地方进行了配置,那么MyBatis按照下面的顺序来加载

    • 1.在properties元素体内指定的属性首先被读取

    • 2.然后根据properties元素中的resource属性读取类路径下属性文件或者根据url属性指定的路径读取属性文件,并覆盖已读取的同名模块

    • 3.最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。

    因此优先级顺序:方法参数传递的属性 > resource/url 属性中指定的配置文件 > properties 属性中指定的属性

    1.1 property子元素

    在MyBatis.xml的配置里面配置如下的编码

    <dataSource type="pooled">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/springdatastudy?serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </dataSource>
    

    1.2 properties配置文件

    使用properties来配置属性,可以方便我们在多个配置文件重复使用,也可以随时修改及日后维护

    • 1.在resources文件夹下面创建datasource.properties
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/springdatastudy?serverTimezone=UTC
    username=root
    password=root
    
    • 2.在MyBatis.xml配置文件的properties节点下引入properties文件
    <properties resource="datasource.properties"/>
    
    <!--数据源-->
    <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </dataSource>
    

    1.3 程序参数传值

    实际工作中,数据库的用户名及密码可能是加密后的字符串。所以在SqlSessionFactoryBuilder处,需要将加密的字符串进行解密。

    /**
     * 模拟字符串解密
     *
     * @param str
     * @return
     */
    public static String decode(String str) {
        return str;
    }
    
    public static void main(String[] args) throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        Properties properties = new Properties();
        properties.load(Resources.getResourceAsStream("datasource.properties"));
        properties.setProperty("username",decode(properties.getProperty("username")));
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,properties);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> users = userDao.getUser();
        for (User u : users) {
            System.out.println(u.toString());
        }
    }
    

    不要使用混合的方式进行属性配置。优先推荐使用properties文件。

    2.settings属性

    这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。

    • 1.cacheEnabled

    boolean属性,默认是true。该配置影响的所有映射器中配置的缓存的全局开关。

    • 2.lazyLoadingEnabled

    boolean属性,默认值是false。延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。

    • 3.aggressiveLazyLoading

    boolean属性,jar版本3.4.1以下是true。3.4.1以上是false。当启用时,任何方法的调用都会加载该对象的所有属性。不开启,按需加载。

    • 4.multipleResultSetsEnabled

    boolean属性,默认值是true。是否允许单一语句返回多结果集合。(需要兼容驱动)

    • 5.useColumnLabel

    boolean属性,默认值为true。使用列标签代替列名。

    • 6.useGeneratedKeys

    boolean属性,默认值为false。允许JDBC支持自动生成主键。如果设置为true,则这个设置强制使用自动生成主键。(需要驱动兼容)

    • 7.autoMappingBehavior

    枚举属性,三个可选值:None(表示取消自动映射)、Partial(表示只会自动映射没有定义嵌套结果集映射的结果集)、Full(表示会自动映射任意复杂的结果集),默认值为:Partial。

    • 8.autoMappingUnknownColumnBehavior

    枚举属性,三个可选值:None(不做任何反应)、WARNING(输出提醒日志,org.apache.ibatis.session.AutoMappingUnknownColumnBehavior日志等级必须设置为Warn)、FAILING(映射失败,抛出SqlSessionException)。默认值为None。

    • 9.defaultExecutorType

    枚举属性,三个可选值:SIMPLE(普通执行器)、REUSE(会重用预处理语句(prepared statements))、BATCH(重用语句并执行批量更新)

    • 10.重用语句并执行批量更新

    任意正整数,默认值没有设置。设置超时时间,它决定驱动等待数据库响应的秒数。

    • 11.defaultFetchSize

    任意正整数,默认值没有设置。为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。

    • 12.safeRowBoundsEnabled

    boolean属性,默认值为false。允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false。

    • 13.safeResultHandlerEnabled

    boolean属性,默认值为true。允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为false。

    • 14.mapUnderscoreToCamelCase

    boolean属性,默认为false。是否开启自动驼峰命名规则(camelcase)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。

    • 15.localCacheScope

    枚举属性,两个枚举属性:SESSION(会缓存一个会话中执行的所有查询)、STATEMENT(本地会话仅用在语句执行上,对相同SqlSession的不同调用将不会共享数据。)。默认值为SESSION。

    • 16.jdbcTypeForNull

    JDBCType属性,常用的属性有:Null、Varchar、Other。当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。

    • 17.lazyLoadTriggerMethods

    指定哪个对象的方法触发一次延迟加载。

    • 18.defaultScriptingLanguage

    指定动态SQL生成的默认语言。

    • 19.defaultEnumTypeHandler

    Specifies the TypeHandler used by default for Enum. (Since: 3.4.5)

    • 20.callSettersOnNulls

    boolean属性,默认值为false。。指定当结果集中值为null的时候是否调用映射对象的 setter(map 对象时为put)方法,这对于有Map.keySet()依赖或null值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。

    • 21.returnInstanceForEmptyRow

    boolean属性,默认值为false。当返回行的所有列都是空时,MyBatis默认返回null。

    • 22.logPrefix

    String类型,指定 MyBatis 增加到日志名称的前缀。

    • 23.logImpl

    枚举值,指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING

    • 24.proxyFactory

    枚举值,指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。CGLIB | JAVASSIST。默认值:JAVASSIST (MyBatis 3.3 or above)

    • 25.vfsImpl

    指定VFS的实现。自定义VFS的实现的类全限定名,以逗号分隔。

    • 26.useActualParamName

    boolean属性,默认值为true。允许使用方法签名中的名称作为语句参数名称。为了使用该特性,你的工程必须采用Java8编译,并且加上-parameters选项。(从3.4.1开始)

    • 27.configurationFactory

    指定一个提供Configuration实例的类.这个被返回的Configuration实例是用来加载被反序列化对象的懒加载属性值. 这个类必须包含一个签名方法static Configuration getConfiguration(). (从 3.2.3 版本开始)

    一个配置完整的 settings 元素的示例如下:

    <settings>
      <setting name="cacheEnabled" value="true"/>
      <setting name="lazyLoadingEnabled" value="true"/>
      <setting name="multipleResultSetsEnabled" value="true"/>
      <setting name="useColumnLabel" value="true"/>
      <setting name="useGeneratedKeys" value="false"/>
      <setting name="autoMappingBehavior" value="PARTIAL"/>
      <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
      <setting name="defaultExecutorType" value="SIMPLE"/>
      <setting name="defaultStatementTimeout" value="25"/>
      <setting name="defaultFetchSize" value="100"/>
      <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>
    

    3.typeAliases(类型别名)

    类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如:

    • MyBatis.xml里面设置别名
    <typeAliases>
        <typeAlias type="model.User" alias="yuser"></typeAlias>
    </typeAliases>
    
    • Mapper.xml文件里面使用
    <select id="getUser" resultType="yuser">
        select * FROM  user;
    </select>
    

    3.1 自动扫描包自定义别名

    如果POJO过多的时候,配置也非常多。这时候,我们可以使用自动扫描包自定义别名的方式。

    • MyBatis.xml里面的设置扫描包的名称
    <typeAliases>
        <package name="model"/>
    </typeAliases>
    
    • POJO上设置别名
    @Alias("sasUser")
    public class User {
    }
    
    • Mapper.xml使用方法
    <select id="getUser" resultType="sasUser">
        select * FROM  user;
    </select>
    

    3.2系统定义别名

    别名 映射的类型
    _byte byte
    _long long
    _short short
    _int int
    _integer int
    _double double
    _float float
    _boolean boolean
    string String
    byte Byte
    long Long
    short Short
    int Integer
    integer Integer
    double Double
    float Float
    boolean Boolean
    date Date
    decimal BigDecimal
    bigdecimal BigDecimal
    object Object
    map Map
    hashmap HashMap
    list List
    arraylist ArrayList
    collection Collection
    iterator Iterator

    4.typeHandlers(类型处理器)

    无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。

    也就是将参数从Java类型(javaType)转换为jdbcType;或者从数据库取出结果把jdbcType转化为javaType。

    typeHandler和typeAliases(类型别名)一样,分为系统定义及用户自定义。

    4.1 系统定义的typeHandler

    类型处理器 Java 类型 JDBC 类型
    BooleanTypeHandler java.lang.Boolean, boolean 数据库兼容的 BOOLEAN
    ByteTypeHandler java.lang.Byte, byte 数据库兼容的 NUMERIC 或 BYTE
    ShortTypeHandler java.lang.Short, short 数据库兼容的 NUMERIC 或 SHORT INTEGER
    IntegerTypeHandler java.lang.Integer, int 数据库兼容的 NUMERIC 或 INTEGER
    LongTypeHandler java.lang.Long, long 数据库兼容的 NUMERIC 或 LONG INTEGER
    FloatTypeHandler java.lang.Float, float 数据库兼容的 NUMERIC 或 FLOAT
    DoubleTypeHandler java.lang.Double, double 数据库兼容的 NUMERIC 或 DOUBLE
    BigDecimalTypeHandler java.math.BigDecimal 数据库兼容的 NUMERIC 或 DECIMAL
    StringTypeHandler java.lang.String CHAR, VARCHAR
    ClobReaderTypeHandler java.io.Reader -
    ClobTypeHandler java.lang.String CLOB, LONGVARCHAR
    NStringTypeHandler java.lang.String NVARCHAR, NCHAR
    NClobTypeHandler java.lang.String NCLOB
    BlobInputStreamTypeHandler java.io.InputStream -
    ByteArrayTypeHandler byte[] 数据库兼容的字节流类型
    BlobTypeHandler byte[] BLOB, LONGVARBINARY
    DateTypeHandler java.util.Date TIMESTAMP
    DateOnlyTypeHandler java.util.Date DATE
    TimeOnlyTypeHandler java.util.Date TIME
    SqlTimestampTypeHandler java.sql.Timestamp TIMESTAMP
    SqlDateTypeHandler java.sql.Date DATE
    SqlTimeTypeHandler java.sql.Time TIME
    ObjectTypeHandler Any OTHER 或未指定类型
    EnumTypeHandler Enumeration Type VARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引)
    EnumOrdinalTypeHandler Enumeration Type 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称)。

    注意点:

    • 1.时间精度,数据精确到天的使用DateOnlyTypeHandler即可,需要精确到秒的用SqlTimestampHandler。也就是Java类型使用java.sql.Timestamp。数据库类型设置为Timestamp或者datetime。

    DateTime与Timestamp区别

    • 时间范围不一样。DateTime时间范围:''1000-01-01 00:00:00''到''9999-12-31 23:59:59''。而Timestamp时间范围:在1970~2037年之间。

    • timestamp与时区有关,而datetime与时区无关。

    • timestamp存储是4个字节存储的,而datetime存储是8个字节存储的。

    4.2 自定义TypeHanlder

    一般情况下,MyBatis系统定义的typeHandler已经应付了大部分场景,但是有时候我们需要特殊处理一些Java类型与JDBC对应的类型,该如何定义。

    • 1.实现接口TypeHandler或者继承BaseTypeHandler
    @MappedTypes(String.class)
    @MappedJdbcTypes(JdbcType.VARCHAR)
    public class ExampleTypeHandler extends BaseTypeHandler<String> {
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
            System.out.println("example setNonNullParameter");
            ps.setString(i,parameter);
        }
    
        @Override
        public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
            System.out.println("example getNullableResult");
            return rs.getString(columnName);
        }
    
        @Override
        public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            System.out.println("example getNullableResult");
            return rs.getString(columnIndex);
        }
    
        @Override
        public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            System.out.println("example getNullableResult");
            return cs.getString(columnIndex);
        }
    }
    

    注释:
    使用@MappedTypes注释,来指定与其关联的Java类型列表。
    使用@MappedJdbcTypes注释,来指定与其关联的JDBC类型列表

    • 2.在MyBatis-config.xml里面配置typeHandler(类型处理器)
    <!--类型处理器-->
    <typeHandlers>
        <typeHandler javaType="string" jdbcType="VARCHAR" handler="utils.ExampleTypeHandler"/>
    </typeHandlers>
    
    • 3.在mapper.xml文件中指定typeHandler进行转换。

    尽管上面我们自定义了类型处理器类,并在MyBatis全局xml里面配置了类型处理器。但是MyBatis还是不会自动启用你定义的typeHandler进行转换结果。需要人为的去指定哪些参数哪些结果类型去用自定义类型处理器。

    需要人为配置jdbcType和javaType。或者直接用typeHandler属性指定。

    定义jdbcType和javaType

    <resultMap id="AllColumnMap" type="model.DateDemo">
        <result column="name" property="name" javaType="string" jdbcType="VARCHAR"/>
        <result column="createdOn" property="createOn"/>
    </resultMap>
    

    直接使用typeHandler

    <resultMap id="AllColumnMap" type="model.DateDemo">
        <result column="name" property="name" javaType="string" jdbcType="VARCHAR" typeHandler="utils.ExampleTypeHandler"/>
        <result column="createdOn" property="createOn"/>
    </resultMap>
    

    select语句

    <select id="getUser" resultType="model.DateDemo" resultMap="AllColumnMap">
        select * from datedemo;
    </select>
    

    4.3 枚举类型的typeHandler

    虽然MyBatis提供了两个转化枚举的typeHandler给我们使用,但是对应枚举却有自己的特殊转换要求

    • org.apache.ibatis.type.EnumTypeHandler

    • org.apache.ibatis.type.EnumOrdinalTypeHandler

    • 定义一个枚举类型类

    public enum Sex {
        MALE(1, "男"),
        FEMALE(2, "女");
        private int id;
    
        private String name;
    
        private Sex(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    

    当只有类用到字段属性Sex时候,才用到枚举类型处理器。一般实际项目中,都是使用int作为枚举类型。这边就跳过介绍。

    5. ObjectFactory对象工厂

    当MyBatis在构建一个结果返回的时候,都会使用ObjectFactory去构建POJO,在MyBatis中可以定制自己的对象工厂。一般而言使用默认的DefaultObjectFactory。这里不在赘述。

    6.environments配置环境

    配置环境可以注册多个数据源(dataSource),每一个数据源分为两大部分,一个是数据库源的配置,另一个是数据库事务(transactionManager)的配置。

    <!--配置环境-->
    <environments default="default">
        <!--环境变量-->
        <environment id="default">
            <!--事务管理器-->
            <transactionManager type="JDBC"></transactionManager>
    
            <!--数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    

    transactionManager配置的是数据库事务。其中type属性有三种配置方式。

    • JDBC,采用JDBC方式管理事务
    • Managed,采用容器方式管理事务,在JNDI数据源中常用
    • 自定义。

    dataSource,是配置数据源连接的信息。type属性有4种。

    • Unpooled,非连接池数据库
    • pooled,连接池数据库
    • jndi,jndi数据源
    • 自定义。

    6.1 数据库事务

    数据库事务是由SqlSession去控制的,可以通过SqlSession提交(commit)或者回滚(rollback)。如果成功就提交,如果失败就回滚。

    try {
        sqlSession.commit();
    } catch (Exception ex) {
        ex.printStackTrace();
        sqlSession.rollback();
    }
    

    7.mappers(映射器)

    上述的一些是MyBatis的一些行为属性配置。那么我们现在要定义SQL映射语句了。但是首先我们需要告诉MyBatis到哪里去找到这些语句。

    可以使用类路径的资源引用,或者完全限定的资源定位符(包括:file:///的URL),或者类名和包名。

    • 1.文件路径引入(推荐)
    <mappers>
        <mapper resource="mapper/DateDemoDao.xml"></mapper>
    </mappers>
    
    • 2.包名引入
    <!-- Register all interfaces in a package as mappers -->
    <mappers>
      <package name="org.mybatis.builder"/>
    </mappers>
    
    
    • 3.使用类注册
    <!-- Using mapper interface classes -->
    <mappers>
      <mapper class="org.mybatis.builder.AuthorMapper"/>
      <mapper class="org.mybatis.builder.BlogMapper"/>
      <mapper class="org.mybatis.builder.PostMapper"/>
    </mappers>
    
    • 4.使用url注册
    <!-- Using url fully qualified paths -->
    <mappers>
      <mapper url="file:///var/mappers/AuthorMapper.xml"/>
      <mapper url="file:///var/mappers/BlogMapper.xml"/>
      <mapper url="file:///var/mappers/PostMapper.xml"/>
    </mappers>
    

    相关文章

      网友评论

        本文标题:3.详解MyBatis的配置文件

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