mysql datetime可以为null

MySQL的DateTime字段默认情况下是允许为NULL的。当使用MyBatis Plus的updateById方法更新数据时,如果DateTime字段为null,会被忽略掉,导致更新失败。为了解决这个问题,可以考虑以下两种方法:

  1. 使用特定的日期值代替null:
    可以选择在DateTime字段为null时,使用一个特定的日期值来代替,比如使用MySQL中的"0000-00-00 00:00:00"或者一个具体的无效日期,来表示该字段的空值。在业务逻辑中,当读取到该特定日期值时,可以将其解释为null。
  2. 使用Java中的Optional类:(推荐)
    可以在Java中使用Optional类来处理DateTime字段的空值。将DateTime字段声明为Optional<LocalDateTime>类型,即可处理可能为null的情况。在查询时,如果DateTime字段为null,将其包装为Optional.empty();在更新时,如果要设置为空值,可以将其设置为Optional.empty(),否则将值包装为Optional.of(value)

以下是第二种方法的示例代码:

User.java:

public class User {
    private Long id;
    private String username;
    private Optional<LocalDateTime> dateTime;
    // getters and setters
}

UserMapper.java:

public interface UserMapper extends BaseMapper<User> {
    // 其他方法...
}

UserService.java:

public class UserService {
    private UserMapper userMapper;

    public UserService(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    public void updateUserDateTime(Long userId, Optional<LocalDateTime> dateTime) {
        User user = new User();
        user.setId(userId);
        user.setDateTime(dateTime);
        userMapper.updateById(user);
    }

    // 其他服务方法...
}

在这个示例中,DateTime字段被声明为Optional<LocalDateTime>类型。在updateUserDateTime方法中,你可以传入Optional.empty()来表示将DateTime字段设置为null。如果要设置具体的值,可以使用Optional.of(value)来包装。

使用Optional类可以更好地表示DateTime字段的空值情况,并与MyBatis Plus的更新方法兼容。当读取和处理数据时,你可以使用Optional类的方法来判断字段是否为null,并进行相应的处理。

查询数据时数据库为null那么程序中也为null,不会再包装一层
理由:为null时不会更新此字段,减少不必要的数据更新

还需要一些转换器

package com.example.demo.handler;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.util.Optional;

@Configuration
public class JacksonConfiguration {

    @Bean
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializerByType(Optional.class, new OptionalSerializer());
        builder.deserializerByType(Optional.class, new OptionalDeserializer());
        return builder;
    }

    public static class OptionalSerializer extends JsonSerializer<Optional<?>> {

        @Override
        public void serialize(Optional<?> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            if (value.isPresent()) {
                gen.writeObject(value.get());
            } else {
                gen.writeNull();
            }
        }
    }

    public static class OptionalDeserializer extends JsonDeserializer<Optional<?>> {

        @Override
        public Optional<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            ObjectMapper mapper = (ObjectMapper) p.getCodec();
            JsonNode node = mapper.readTree(p);
            if (node.isNull()) {
                return null;
            }
            if ("".equals(node.textValue())) {
                return Optional.empty();
            } else {
                Object value = mapper.treeToValue(node, Object.class);
                return Optional.ofNullable(value);
            }
        }
    }
}

package com.example.demo.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.stereotype.Component;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.Optional;

@Component
public class OptionalDateTypeHandler extends BaseTypeHandler<Optional<Date>> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Optional<Date> parameter, JdbcType jdbcType) throws SQLException {

        ps.setObject(i, parameter.orElse(null));
    }

    @Override
    public Optional<Date> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Date date = rs.getTimestamp(columnName);
        if (date == null) {
            return null;
        }
        return Optional.ofNullable(date);
    }

    @Override
    public Optional<Date> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Date date = rs.getTimestamp(columnIndex);
        if (date == null) {
            return null;
        }
        return Optional.ofNullable(date);
    }

    @Override
    public Optional<Date> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Date date = cs.getTimestamp(columnIndex);
        if (date == null) {
            return null;
        }
        return Optional.ofNullable(date);
    }
}

可以兼容三种场景

  1. null 代表不更新
  2. “” 代表更新为null
  3. “2023-06-28 16:27:21” 代表更新具体的值

最后在项目中并没有使用这种方式

  1. 因为相比于直接使用Date类型,这种方式还需要再次进行包装,且前端传时间字段的接口并没有太多。

关联文章 mybatisplus生成工具自定义类型转换

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值