Mybatis(四)——项目优化

本文深入探讨MyBatis框架的高级配置技巧,包括数据库连接配置、全局参数设定、别名定义、内置与自定义类型处理器的应用。通过实例演示如何在资源文件中设置数据库属性,配置全局参数,定义实体类别名,以及实现复杂类型的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. JDBC属性文件

在资源文件夹下新建db.properties文件,其内容如下

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3307/mybatis
username=root
password=root

修改conf.xml的内容
首先引入资源文件db.properties

<properties resource="db.properties"/>

然后配置数据库信息

<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>

这样的话,只需要在资源文件里修改数据库信息

2. Mybatis全局参数

可以在conf.xml里添加全局参数,初学者不建议使用

<configuration>
    <properties resource="db.properties"/>
    <settings>
        <setting name="cacheEnabled" value="false"/>
        <setting name="lazyLoadingEnabled" value="false"/>
    </settings>
    <environments default="development">
        ......
    </environments>
    <mappers>
        ......
    </mappers>
</configuration>

3. 别名

在Mapper-interface.xml里,返回值类型为com.santiago.maven.Student,我们可以为其定义别名,使得代码简洁。
在conf.xml里,可加入如下配置

  • 定义别名时,不考虑大小写
    定义别名有两种方式:1. 定义单个别名;2. 批量定义别名
  1. 定义单个别名
    <typeAliases>
        <typeAlias type="com.santiago.maven.Student" alias="Student"/>
    </typeAliases>
  1. 批量定义别名
    将包的名称引入,别名默认为该包中类的名字(不考虑大小写,不带包名),如下所示
    <typeAliases>
        <package name="com.santiago.maven"/>
    </typeAliases>

Mybatis自带的别名,不用定义就可以使用
在这里插入图片描述

4. 类型处理器

想象这么两个场景。

  • 在类中用String类型修饰性别(男:male;女:female),在数据库中用int类型来修饰男女(男:1;女:0)。那么这两者怎么映射?
  • 在类中编号用id表示,而在数据库中编号用no表示。那么这两者怎么映射?

这就需要用到类型处理器,Mybatis有很多内置的类型处理器,如果内置的不够用,还可以自定义处理器

4.1 内置类型处理器
类型处理器Java 类型JDBC 类型
BooleanTypeHandlerjava.lang.Boolean, boolean数据库兼容的 BOOLEAN
ByteTypeHandlerjava.lang.Byte, byte数据库兼容的 NUMERIC 或 BYTE
ShortTypeHandlerjava.lang.Short, short数据库兼容的 NUMERIC 或 SMALLINT
IntegerTypeHandlerjava.lang.Integer, int数据库兼容的 NUMERIC 或 INTEGER
LongTypeHandlerjava.lang.Long, long数据库兼容的 NUMERIC 或 BIGINT
FloatTypeHandlerjava.lang.Float, float数据库兼容的 NUMERIC 或 FLOAT
DoubleTypeHandlerjava.lang.Double, double数据库兼容的 NUMERIC 或 DOUBLE
BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERIC 或 DECIMAL
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任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的序数值(而不是名称)。
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.YearMonthVARCHAR 或 LONGVARCHAR
JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE
4.2 自定义类型处理器

自定义类型处理器需要实现TypeHandler接口,通过阅读源码,发现TypeHandler接口有一个实现类BaseTypeHandler。
因此创建自定义类型处理器有两种方法:
1. 实现TypeHandler接口
2. 继承BaseTypeHandler
我们使用第二种较为简单的方法

使用自定义类型转换器的步骤

4.2.1 首先修改Student类和数据库,添加sex属性,在数据库中,设置stuno为主键
4.2.2 新建一个转换器类StringAndInt.java,继承自BaseTypeHandler
public class StringAndInt extends BaseTypeHandler<String> {
}

其中泛型类型根据自己使用的javaType修改,并重写方法,接下来分别介绍重写的四个方法

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, String parameter, JdbcType jdbcType) throws SQLException {
        if("female".equals(parameter)){
            preparedStatement.setInt(i,0);
        }else if("male".equals(parameter)){
            preparedStatement.setInt(i, 1);
        }
    }

该方法完成从java到DB这个方向的类型转换,其中参数:

  • PreparedStatement preparedStatement:PreparedStatement对象
  • int i:PreparedStatement对象操作参数的位置
  • String parameter:java类型
  • JdbcType jdbcType:jdbc数据库类型
    其余三种方式均是从DB往java这个方向转换

根据列名拿返回结果

    @Override
    public String getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        int sex = resultSet.getInt(columnName);
        return sex == 1 ? "male" : "female";
    }

根据下标拿返回结果

    @Override
    public String getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        int sex = resultSet.getInt(columnIndex);
        return sex == 1 ? "male" : "female";
    }

根据存储过程拿返回结果

    @Override
    public String getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        int sex = callableStatement.getInt(columnIndex);
        return sex == 1 ? "male" : "female";
    }
4.2.3 在配置文件配置类型处理器

在conf.xml里添加如下内容

    <typeHandlers>
        <typeHandler handler="com.santiago.convertor.StringAndInt" javaType="String" jdbcType="INTEGER"/>
    </typeHandlers>

编写Mapper-interface.xml映射文件 显然用到resultMap

注意:主键与非主键的表达方式不同,例如,stuno为主键,则用id标签,stuName为非主键,则用result标签

    <select id="queryStudentByStuNoWithConvertor" resultMap="SR" parameterType="int">
        select * from student where stuno = #{stuno}
    </select>
    <resultMap id="SR" type="Student">
        <id property="stuNo" column="stuno"/>
        <result property="stuName" column="stuname"/>
        <result property="stuAge" column="stuage"/>
        <result property="gradeName" column="gradename"/>
        <result property="sex" column="sex" javaType="String" jdbcType="INTEGER"/>
    </resultMap>

插入和更新操作不要忘了修改,需要注意的地方如下
在这里插入图片描述

    <update id="updateStudentByStuNo"  parameterType="Student">
        update student set stuname = #{stuName}, stuage = #{stuAge}, gradename = #{gradeName}, sex = #{sex, javaType=String, jdbcType=INTEGER} where stuno = #{stuNo}
    </update>
    <insert id="addStudent" parameterType="Student">
        insert into student(stuno,stuname,stuage,gradename,sex) values(#{stuNo},#{stuName},#{stuAge},#{gradeName},sex = #{sex, javaType=String, jdbcType=INTEGER})
    </insert>
4.2.4 测试

不使用类型转换器的情况
在这里插入图片描述
使用类型转换器的情况
在这里插入图片描述
在这里插入图片描述
注意:在xml文件中,jdbcType要写成大写INTEGER,否则报错,我也不知道为什么

对于第二种场景,类中属性名和表中字段名不能够自动匹配,也需要用到resultMap,以查询单个学生为例

    <select id="queryStudentByStuNo" resultMap="updateStudent" parameterType="int">
        select * from student where stuno = #{stuno}
    </select>
    <resultMap id="updateStudent" type="Student">
        <id property="id" column="stuno"/>
        <result property="stuName" column="stuname"/>
        <result property="stuAge" column="stuage"/>
        <result property="gradeName" column="gradename"/>
        <result property="sex" column="sex" javaType="String" jdbcType="INTEGER"/>
    </resultMap>

只是把属性名properrty和列名column进行了修改,使其匹配。如果属性名和列名一致,不需要添加resultMap

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值