MyBatis类型转换、插件

MyBatis在处理数据库查询结果和Java对象之间的类型转换时,会自动根据Java对象属性的数据类型和数据库字段的数据类型进行匹配。如果Java对象属性的数据类型与数据库字段的数据类型不匹配,MyBatis会尝试进行自动的类型转换。以下是MyBatis中的常见类型转换情况:

  1. 基本类型转换:MyBatis会自动进行基本数据类型和对应的包装类型之间的转换,如int和Integer、long和Long、float和Float等。

  2. 日期类型转换:MyBatis会自动将数据库中的日期类型(如DATE、TIME、TIMESTAMP)转换为Java的java.util.Date类型或者java.time.LocalDate、java.time.LocalTime、java.time.LocalDateTime类型。

  3. 枚举类型转换:MyBatis会将数据库中存储的枚举类型转换为Java的枚举类型。

  4. 字符串类型转换:MyBatis会自动将数据库中的字符类型转换为Java的String类型。

  5. 自定义类型转换:如果需要对特定类型进行自定义转换,可以实现TypeHandler接口,并在MyBatis的配置文件中进行配置。TypeHandler接口包含了Java类型与JDBC类型之间的转换方法。

例如,假设数据库中的字段为VARCHAR类型,而Java对象的对应属性为Integer类型,MyBatis会尝试将VARCHAR类型的数据库字段值转换为Integer类型。如果数据库中的值无法转换为Integer类型,会抛出异常。

若MyBatis的默认类型转换无法满足需求,你可以实现自定义的TypeHandler来处理特殊的类型转换。以下是一个自定义TypeHandler的简单示例,用于将数据库的CHAR类型转换为Java的Boolean类型:

public class CharToBooleanTypeHandler implements TypeHandler<Boolean> {
    @Override
    public void setParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter ? "Y" : "N");
    }

    @Override
    public Boolean getResult(ResultSet rs, String columnName) throws SQLException {
        String value = rs.getString(columnName);
        return "Y".equals(value);
    }

    @Override
    public Boolean getResult(ResultSet rs, int columnIndex) throws SQLException {
        String value = rs.getString(columnIndex);
        return "Y".equals(value);
    }

    @Override
    public Boolean getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String value = cs.getString(columnIndex);
        return "Y".equals(value);
    }
}

然后在MyBatis的配置文件中配置该TypeHandler:

<typeHandlers>
    <typeHandler handler="com.example.CharToBooleanTypeHandler" javaType="java.lang.Boolean" jdbcType="CHAR"/>
</typeHandlers>

通过自定义TypeHandler,你可以灵活地处理复杂的类型转换需求,使MyBatis的数据类型匹配更加灵活和方便。

 

MyBatis插件是一种扩展机制,允许开发者在MyBatis的执行过程中进行拦截和修改。通过插件,可以在MyBatis执行SQL语句前后做一些自定义的处理,例如增加日志、统计SQL执行时间、动态修改SQL等。MyBatis插件是一个非常有用且强大的特性,可以帮助开发者在不改变源码的情况下扩展和定制MyBatis的功能。

插件要实现org.apache.ibatis.plugin.Interceptor接口,并实现其三个方法:

  1. intercept:用于对MyBatis的执行过程进行拦截和修改,包括SQL语句执行前后的处理。

  2. plugin:用于包装目标对象,创建一个代理对象,并返回该代理对象。该代理对象会拦截目标对象的方法调用。

  3. setProperties:用于设置插件的属性,这些属性可以在插件的配置中指定。

以下是一个简单的MyBatis插件示例,用于记录SQL执行时间:

@Intercepts({
    @Signature(type = StatementHandler.class, method = "update", args = { Statement.class }),
    @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class })
})
public class SqlExecutionTimeInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = invocation.proceed();
        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;
        System.out.println("SQL Execution Time: " + executionTime + " ms");
        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以在这里读取配置文件中的属性
    }
}

在上述示例中,我们实现了一个简单的插件,用于记录SQL执行时间。该插件拦截了StatementHandler的update和query方法,记录了SQL执行前后的时间,并输出到控制台。

然后,在MyBatis的配置文件中配置该插件:

<plugins>
    <plugin interceptor="com.example.SqlExecutionTimeInterceptor" />
</plugins>

通过这种方式,我们可以在不修改源码的情况下,灵活地定制MyBatis的功能,实现日志、性能监控、权限控制等扩展。值得注意的是,插件的拦截器顺序会影响执行效果,你可以通过在插件配置中指定<plugin>的顺序来控制拦截器的执行顺序。