mybatis(二)xml配置文件详细说明

mybatis(二)xml配置方式详细说明


详细说明几个比较重要的mybatis配置项

2.1、使用properties配置属性

在日常工作中,我们可能需要将一些配置信息写在一个单独的properties配置文件中便于管理,mybatis对此进行了很好的支持

2.1.1、引入外部properties文件或在properties标签内定义属性
  • 创建db.properties文件
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
driverClass=com.mysql.cj.jdbc.Driver
username=root
pwd=Test#123345
  • 在mybatis主配置文件导入db.properties
<?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 resource="db.properties">
        <property name="username" value="root"/>
    </properties>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driverClass}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射扫描 -->
    <mappers>
        <mapper class="com.szm.mapper.UserMapper"/>
    </mappers>
</configuration>
2.1.1.1、如果一个属性在不只一个地方进行了配置,加载顺序(官方解释)如下:
  • 首先读取在 properties 元素体内指定的属性。

  • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。

  • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

总结:如果存在同名属性,resource指向的文件中的属性值将会覆盖元素体内指定的属性值。

2.2、类型别名(typeAliases)

2.2.1、对象别名
  • 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 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 resource="db.properties">
        <property name="username" value="root"/>
    </properties>
    <!-- 配置别名-->
    <typeAliases>
        <typeAlias alias="user" type="com.szm.pojo.User"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driverClass}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射扫描 -->
    <mappers>
        <mapper class="com.szm.mapper.UserMapper"/>
    </mappers>
</configuration>

​ 在指定了别名之后,就可以在mapper的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.szm.mapper.UserMapper">
    <select id="selectUser" resultType="user">
    select * from user
  </select>
</mapper>
2.2.2、指定包名,自动生成别名
  • typeAliases也可以指定一个包名,例如:
<typeAliases>
  <package name="com.szm.pojo"/>
</typeAliases>

​ 在指定了一个包名之后,会使用类名的首字母小写的非限定类名来作为它的别名,例如:

//这里的话就会用user来作为别名
public class User {
    private int id;
    private String name;
    private String pwd;
}

​ 也可以使用注解结合typeAliases指定包名来实现定义别名。例如:

<typeAliases>
  <!--指定包路径 -->
  <package name="com.szm.pojo"/>
</typeAliases>
//使用注解指定别名
@Alias("user")
public class User {
    private int id;
    private String name;
    private String pwd;
}
2.2.3内置的java类型别名
别名类型
bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection

2.3 、类型处理器(typeHandlers)

2.3.1、何为类型处理器:
  • 官方解释:

MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

  • 来个冗长的类型处理器对应的表吧:
类处理器名称Java类型jdbc类型
BooleanTypeHandlerjava.lang.Boolean, boolean数据库兼容的 BOOLEAN
ByteTypeHandlerjava.lang.Byte, byte数据库兼容的 NUMERICBYTE
ShortTypeHandlerjava.lang.Short, short数据库兼容的 NUMERICSMALLINT
IntegerTypeHandlerjava.lang.Integer, int数据库兼容的 NUMERICINTEGER
LongTypeHandlerjava.lang.Long, long数据库兼容的 NUMERICBIGINT
FloatTypeHandlerjava.lang.Float, float数据库兼容的 NUMERICFLOAT
DoubleTypeHandlerjava.lang.Double, double数据库兼容的 NUMERICDOUBLE
BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERICDECIMAL
StringTypeHandlerjava.lang.StringCHAR, VARCHAR
ClobReaderTypeHandlerjava.io.Reader-
ClobTypeHandlerjava.lang.StringCLOB, LONGVARCHAR
NStringTypeHandlerjava.lang.StringNVARCHAR, NCHAR
NClobTypeHandlerjava.lang.StringNCLOB
BlobInputStreamTypeHandlerjava.io.InputStream-
ByteArrayTypeHandlerbyte[]数据库兼容的字节流类型
BlobTypeHandlerbyte[]BLOB, LONGVARBINARY
DateTypeHandlerjava.util.DateTIMESTAMP
DateOnlyTypeHandlerjava.util.DateDATE
TimeOnlyTypeHandlerjava.util.DateTIME
SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
SqlDateTypeHandlerjava.sql.DateDATE
SqlTimeTypeHandlerjava.sql.TimeTIME
ObjectTypeHandlerAnyOTHER 或未指定类型
EnumTypeHandlerEnumeration TypeVARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值)
EnumOrdinalTypeHandlerEnumeration Type任何兼容的 NUMERICDOUBLE 类型,用来存储枚举的序数值(而不是名称)。
SqlxmlTypeHandlerjava.lang.StringSQLXML
InstantTypeHandlerjava.time.InstantTIMESTAMP
LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
LocalDateTypeHandlerjava.time.LocalDateDATE
LocalTimeTypeHandlerjava.time.LocalTimeTIME
OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
YearTypeHandlerjava.time.YearINTEGER
MonthTypeHandlerjava.time.MonthINTEGER
YearMonthTypeHandlerjava.time.YearMonthVARCHARLONGVARCHAR
2.3.2、测试自定义的类型处理器(官方例子)

自定义类型处理器,将getNullableResult获取结果返回值写一个固定的值测试是否生效

package com.szm.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


@MappedJdbcTypes(JdbcType.VARCHAR)
public class MyTypeHandler extends BaseTypeHandler<String> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return "myTypeHandlerString-getNullableResult(ResultSet rs, String columnName)";
        //return rs.getString(columnName);
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return "myTypeHandlerString-getNullableResult(ResultSet rs, int columnIndex)";
        // return rs.getString(columnIndex);
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return "myTypeHandlerString-getNullableResult(CallableStatement cs, int columnIndex)";
       // return cs.getString(columnIndex);
    }
}

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 resource="db.properties">
        <property name="username" value="root"/>
    </properties>
    <!-- 配置别名-->
    <typeAliases>
        <typeAlias alias="user" type="com.szm.pojo.User"/>
    </typeAliases>
    <!--配置自定义类型处理器 -->
    <typeHandlers>
        <typeHandler handler="com.szm.handler.MyTypeHandler"/>
    </typeHandlers>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driverClass}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射扫描 -->
    <mappers>
        <mapper class="com.szm.mapper.UserMapper"/>
    </mappers>
</configuration>

测试代码:

  @Test
    public void test() throws IOException {
        String resource = "mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.selectUserLike("user");
        users.stream().forEach((e)->{
            System.out.println(e);
        });
        sqlSession.close();
    }

结果可以看到所有的String类型参数结果都是我们定义的固定返回值:

User(id=1, name=myTypeHandlerString-getNullableResult(ResultSet rs, String columnName), pwd=myTypeHandlerString-getNullableResult(ResultSet rs, String columnName))
User(id=2, name=myTypeHandlerString-getNullableResult(ResultSet rs, String columnName), pwd=myTypeHandlerString-getNullableResult(ResultSet rs, String columnName))
User(id=3, name=myTypeHandlerString-getNullableResult(ResultSet rs, String columnName), pwd=myTypeHandlerString-getNullableResult(ResultSet rs, String columnName))

2.4、对象工厂(objectFactory)

2.4.1、官方解释

每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现。

2.4.2、代码实现
  • 在User对象中新增一个数据库中没有的扩展字段

    package com.szm.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    
    
    @Data
    public class User {
        private int id;
        private String name;
        private String pwd;
        //查询结果没有这个字段
        private String extendField;
    
    }
    
    
  • 自定义对象工厂

package com.szm.factory;


import com.szm.pojo.User;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

import java.util.List;
import java.util.UUID;

public class MyObjectFactory extends DefaultObjectFactory {
    @Override
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        T t = super.create(type, constructorArgTypes, constructorArgs);
        if (User.class.isAssignableFrom(type)) {
            User user = (User) t;
            //给这个对象的ExtendField赋值一个随机值
            user.setExtendField(UUID.randomUUID().toString());
        }
        return t;
    }
}

  • 配置自定义对象工厂
<?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 resource="db.properties">
        <property name="username" value="root"/>
    </properties>
    <!-- 配置别名-->
    <typeAliases>
        <typeAlias alias="user" type="com.szm.pojo.User"/>
    </typeAliases>
    <!--配置自定义类型处理器 -->
    <typeHandlers>
        <typeHandler handler="com.szm.handler.MyTypeHandler"/>
    </typeHandlers>
    <!-- 配置自定义对象工厂-->
    <objectFactory type="com.szm.factory.MyObjectFactory"/>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driverClass}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射扫描 -->
    <mappers>
        <mapper class="com.szm.mapper.UserMapper"/>
    </mappers>
</configuration>
  • 测试
@Test
    public void test() throws IOException {
        String resource = "mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.selectUserLike("user");
        users.stream().forEach((e)->{
            System.out.println(e);
        });
        sqlSession.close();
    }
  • 结果
User(id=1, name=user1, pwd=pwd1, nickname=123)
User(id=2, name=user2, pwd=pwd2, nickname=123)
User(id=3, name=user3, pwd=pwd3, nickname=123)

2.5、映射器(mappers)

2.5.1、xml配置映射器
  • 配置文件在java包路径下
<!-- 使用相对于类路径的资源引用 ,如果主配置文件在resource下,则应该如下使用-->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
  • 当前文件系统下的任意一个位置
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
  • 直接指定mapper接口位置(这种方式你必须在接口使用注解方式定义好要执行的sql语句)
<!--接口全路径 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

<!-- 包路径,将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值