Mybatis支持实体类LocalDateTime格式化转化解析

本文介绍了如何在Mybatis中将Date类型转换为LocalDateTime,并确保查询与数据库TIMESTAMP类型的兼容性。讲解了自定义TypeHandler的实现和日期格式化策略,以及如何在JSON序列化中统一处理LocalDateTime。

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

Mybatis生成的映射实体类对应的日期类型是Date类型,我们应该改成LocatDateTime等Java8新出的安全日期类型,但是这样实体类在mybatis执行映射解析上跟数据库的类型是匹配不上的,会报类型格式不匹配等问题。

解决方法:统计设置日期类型转换,执行查询获取的日期需要映射为LocatDateTime类型,执行新增更新等操作时将LocatDateTime日期对象转成与数据库相匹配的类型。代码如下:

import com.common.constant.DateConstant;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.stereotype.Component;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.ZoneId;

/**
 * Description:Mybatis支持LocalDateTime格式化
 * @version 1.0.0
 * @date 2021/10/8
 */
@Component
//定义转换器支持的JAVA类型
@MappedTypes(LocalDateTime.class)
//定义转换器支持的数据库类型
@MappedJdbcTypes(value = JdbcType.TIMESTAMP, includeNullJdbcType = true)
public class CustomLocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType)
            throws SQLException {
        if (parameter != null) {
            // ps.setString(i, DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS.format(parameter));
            // 不用解析为字符串,不然与数据库TIMESTAMP类型不匹配
            // setDate(),sql.Date只能精确到年月日,采用Timestamp时间戳方式
            ps.setTimestamp(i, Timestamp.valueOf(parameter));
        }
    }

    @Override
    public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String target = rs.getString(columnName);
        if (StringUtils.isBlank(target)) {
            return null;
        }
        // 日期值后面多了.0,去掉
        target = target.substring(0, target.length() - 2);
        return LocalDateTime.parse(target, DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS);
    }

    @Override
    public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String target = rs.getString(columnIndex);
        if (StringUtils.isBlank(target)) {
            return null;
        }
        // 日期值后面多了.0,去掉
        target = target.substring(0, target.length() - 2);
        return LocalDateTime.parse(target, DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS);
    }

    @Override
    public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String target = cs.getString(columnIndex);
        if (StringUtils.isBlank(target)) {
            return null;
        }
        // 日期值后面多了.0,去掉
        target = target.substring(0, target.length() - 2);
        return LocalDateTime.parse(target, DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS);
    }
}
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.mapper.autoconfigure.ConfigurationCustomizer;

/**
 * Description:Mybatis配置
 * @version 1.0.0
 * @date 2021/10/8
 */
@Configuration
public class MybatisConfigurationCustomizer implements ConfigurationCustomizer {

    @Override
    public void customize(org.apache.ibatis.session.Configuration configuration) {
        TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        typeHandlerRegistry.register(CustomLocalDateTimeTypeHandler.class);
    }
}
import java.time.format.DateTimeFormatter;

/**
 * Description:日期常量
 * @version 1.0.0
 * @date 2021/10/8
 */
public interface DateConstant {

    /**
     * Java8日期格式
     */
    DateTimeFormatter FORMAT_YYYY_MM_DD = DateTimeFormatter.ofPattern(YYYY_MM_DD);
    DateTimeFormatter FORMAT_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);

}

这样与数据库映射实体类的日期属性改为LocatDateTime类型时,也可以正常执行Mybatis操作,代码实现主要也是监听TIMESTAMP类型的sql字段进行解析转化,如果是获取则转化为LocatDateTime日期类,如果是更新则解析成java.sql包下可与数据库类型匹配的时间戳类型。

另外,如下是统一按日期格式json序列化LocatDateTime日期类型的代码:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.common.constant.DateConstant;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * Description:统一json日期格式配置
 * @version 1.0.0
 * @date 2021/10/8
 */
@Configuration
public class ObjectMapperConfiguration {

    private static ObjectMapper MAPPER;

    public static ObjectMapper getMapper() {
        if (MAPPER != null) {
            return MAPPER;
        }
        return new ObjectMapper();
    }

    @Bean
    @Primary
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        MAPPER = builder.createXmlMapper(false).build();
        return MAPPER;
    }

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer enumCustomizer() {
        return builder -> builder
                .deserializerByType(LocalDateTime.class,
                        new LocalDateTimeDeserializer(DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS))
                .deserializerByType(LocalDate.class,
                        new LocalDateDeserializer(DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS))
                .serializerByType(LocalDateTime.class,
                        new LocalDateTimeSerializer(DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS))
                .serializerByType(LocalDate.class, new LocalDateSerializer(DateConstant.FORMAT_YYYY_MM_DD_HH_MM_SS))
                ;
    }
}

MyBatis中,如果想将`LocalDateTime`类型的值从数据库映射到Java实体类中,通常涉及到序列化和反序列化的过程。MyBatis本身并不直接支持`LocalDateTime`,但我们可以借助第三方库或者自定义处理来完成转换。 **Option 1: Jackson、Gson等JSON库** - **Jackson**: 在MyBatis的XML映射文件中,你可以使用`@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")`注解来指定日期格式,然后在实体类上使用`@JsonIgnoreProperties(ignoreUnknown = true)`忽略未知属性,避免自动转换引发的问题。例如: ```xml <select id="select" resultType="com.example.YourEntity"> SELECT ..., JSON_FORMAT(your_localdatetime_column, 'yyyy-MM-dd HH:mm:ss') as your_field </select> ``` 然后在实体类中处理: ```java public class YourEntity { private LocalDateTime yourField; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") public LocalDateTime getYourField() { return yourField; } public void setYourField(LocalDateTime yourField) { this.yourField = yourField; } } ``` - **Gson**: 同理,你可以使用Gson的`@Expose`和`@SerializedName`注解进行格式化。 **Option 2: 自定义ResultHandler** 你还可以编写一个自定义的`ResultHandler`来处理转换过程。在`doQuery`方法内部,针对`your_localdatetime_column`字段,手动将其转换为`LocalDateTime`: ```java List<YourEntity> entities = sqlSession.selectList("select", new RowBounds(0, -1), new YourEntityHandler()); ``` ```java public static class YourEntityHandler implements ResultHandler<YourEntity> { private final Executor executor; private final ResultSetHandler<YourEntity> handler; public YourEntityHandler(Executor executor, ResultSetHandler<YourEntity> handler) { this.executor = executor; this.handler = handler; } @Override public void handleResult(ResultSet rs) throws SQLException { while (rs.next()) { YourEntity entity = handler.handleResult(rs); entity.setYourField(LocalDateTime.parse(rs.getString("your_field"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // 添加到列表中 } } } ``` **Option 3: MyBatis Plus扩展** 如果使用MyBatis Plus,你可以创建一个拦截器(Interceptor)在查询结果返回前进行格式化。 无论哪种方式,记得在使用之前确保已经导入了相应的日期时间库,例如`java.time`包。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wzq_55552

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值