实战:springboot用LocalDateTime快速替换Date

概叙

实战:早点用JDK8中的java.time来替换java.util.Date-CSDN博客

Spring Boot项目中大家从Date升级到LocalDateTime最关心以下两个问题:

  • 使用LocalDateTime类型字段作为接口出入参数,能正常映射转换前端传入的参数吗?返回参数前端是否能收到一个正常的日期时间字段值?

  • 使用LocalDateTime类型作为数据库实体类对象字段,能正常写入数据库和读取吗?简单来说就是看数据库能否正常序列化和反序列化LocalDateTime等Java 8提供的全新日期时间类型。

LocalDateTime 在设计上更加现代化、易用且安全,克服了 Date 和 Calendar 的诸多缺点。虽然它们在功能上有重叠之处,但 LocalDateTime 提供了更好的 API 和功能,推荐在 Java 8 及以上版本中使用新的日期和时间 API。

替换虽然快,但是必要的测试不可少,替换完了记得全网回归测试。

LocalDateTime作为接口出入参数

我也挺好奇的,能不能丝滑地从Date过渡到LocalDateTime,先来看看作为接口出入参数与前端交互是什么个情况。话不多说,直接上示例,

先声明一个用户信息参数对象:

@Data
public class UserParam {private Long id;private String name;private LocalDate birthday;private LocalDateDate createTime;
}

接口调用:这里userDTO和上面的参数字段一样的,为了看看接口返回结果罢了

  @PostMapping("/date")public UserDTO testLocalDateTime(@RequestBody UserParam param) {UserDTO userDTO = new UserDTO();BeanUtils.copyProperties(param, userDTO);System.out.println(userDTO);return userDTO;}

没想到执行结果报错~~~出师不利,具体情况如下所示:HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime` from String "2024-06-30 12:12:56":

控制台错误信息:不能正常解析转换成LocalDateTime,这真是怕啥来啥哦。。。

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime` from String "2024-06-30 12:12:56": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2024-06-30 12:12:56' could not be parsed at index 10; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "2024-06-30 12:12:56": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2024-06-30 12:12:56' could not be parsed at index 10

接下来说说解决方案:

方案1:在字段属性上加上注解@JsonFormat格式化日期时间,这种方式简单直接

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")

UserParam加上之后控制入参格式和UserDTO加上控制出参格式:

@Data
public class UserParam {private Long id;private String name;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd")private LocalDate birthday;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;
}
@Data
public class UserDTO {private Long id;private String name;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd")private LocalDate birthday;@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;
}

再次调用上面示例接口就能正常接受参数和返回结果了。

这种方式简单是简单,但就是比较重复不够优雅,一个项目中有这么多接口出入参对象一个个去打上注解不得累个半死,繁琐滴很,能不能一次性搞定,来个全局配置啥的就行那种?肯定有了,下来就来看看。

方案2:全局配置解析LocalDateTime

我们知道Spring Boot 已经为我们提供了日期格式化配置项: spring.jackson.date-format

spring:jackson:date-format: yyyy-MM-dd HH:mm:sslocale: zh_CNtime-zone: GMT+8default-property-inclusion: non_null

这个配置项我们之前映射Date也是需要配置的,否则日期解析不成功。所以我们只需要在配置类读取该配置项对LocalDateTime的格式化转换即可:

@Configuration
public class LocalDateTimeSerializerConfig {@Beanpublic LocalDateTimeSerializer localDateTimeSerializer(JacksonProperties properties) {String dateFormat = properties.getDateFormat();if (StringUtils.isBlank(dateFormat)) {dateFormat = "yyyy-MM-dd HH:mm:ss";}return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateFormat));}@Beanpublic LocalDateTimeDeserializer localDateTimeDeserializer(JacksonProperties properties) {String dateFormat = properties.getDateFormat();if (StringUtils.isBlank(dateFormat)) {dateFormat = "yyyy-MM-dd HH:mm:ss";}return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateFormat));}@Beanpublic Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(LocalDateTimeSerializer localDateTimeSerializer, LocalDateTimeDeserializer localDateTimeDeserializer) {return builder -> {// 序列化builder.serializerByType(LocalDateTime.class, localDateTimeSerializer);// 反序列化builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer);};}}

上面出入参对象去掉注解@JsonFormat,重新启动项目调用接口发现同样正常输出:

LocalDateTime作为实体类字段正常写入数据库和读取

上面解决了作为接口出入参数映射转换问题,现在来看看作为数据库实体类字段能否正常写入和读取。

实体类user

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "tb_user")
@ExcelIgnoreUnannotated
public class User {@TableId(type = IdType.AUTO)private Long id;private String userNo;private Integer gender;private String name;private LocalDate birthday;private String phone;private String email;private Integer isDelete;private String address;private LocalDateTime createTime;
}

这里我们使用orm框架是:mybatis

public interface UserDAO extends BaseMapper<User> {
}

构建单元测试用例如下:

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceImplTest {@Resourceprivate UserDAO userDAO;@Testpublic void testWriteLocalDateTime() {User user = User.builder().id(1L).userNo("001").gender(0).name("张三").phone("12234").birthday(LocalDate.now()).createTime(LocalDateTime.now()).build();userDAO.insert(user);}}

正常写入数据库,开心吧。下面来看看读取:

   @Testpublic void testReadLocalDateTime() {User user = userDAO.selectById(1L);System.out.println(user);}

控制台打印如下:

User(id=1, userNo=001, gender=0, name=张三, birthday=2024-07-03, phone=12234, email=null, isDelete=0, address=null, createTime=2024-07-03T16:09:12)

完美哈。一切都是那么顺风又顺水。那下面我们来看看出问题的情况,把上面的依赖版本改改:

      <!-- MySQL连接驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.26</version></dependency><!-- mp依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency>

再次执行测试用例:

@Testpublic void testReadLocalDateTime() {User user = userDAO.selectById(1L);System.out.println(user);}

控制台报错了:

org.springframework.dao.TransientDataAccessResourceException: Error attempting to get column 'birthday' from result set.  Cause: java.sql.SQLException: Conversion not supported for type java.time.LocalDate
; Conversion not supported for type java.time.LocalDate; nested exception is java.sql.SQLException: Conversion not supported for type java.time.LocalDate

是的,我们担心的情况出现了,数据库不能正常序列化转换LocalDate了....

这里不兜圈子了直接说原因吧,mybatis-plus3.5.2是基于mybaits 3.5.10开发的,mybatis3.5.0及其之前是支持对LocalDateTime类型转换,然而从  MyBatis 3.5.1 开始,不再处理 LocalDateTime (还包括:LocalDate 、 LocalTime )类型的转换而是交由 JDBC 组件,也就是 mysql-connector-java 来实现,5.1.26这个版本压根没实现转换,所以报错了。所以最好使用高一点的版本(重点  不建议直接用mybatis-plus;mybatis-plus只是在mybatis的基础上做增强,没有必要图那点方便,mybatis已经够用了 )

     <!-- MySQL连接驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.9</version></dependency>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/873613.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

贪心算法总结(1)

一、贪心算法简介 常用方法&#xff1a;交换论证法、数学归纳法、反证法、分类讨论 二、柠檬水找零&#xff08;交换论证法&#xff09; . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool lemonadeChange(vector<int>& bills) {int five0,t…

【考研数学】线代满分经验分享+备考复盘

我一战二战复习都听了李永乐的线代课&#xff0c;二战的时候只听了一遍强化&#xff0c;个人感觉没有很乱&#xff0c;永乐大帝的课逻辑还是很清晰的。 以下是我听向量这一章后根据听课内容和讲义例题总结的部分思维导图&#xff0c;永乐大帝讲课的时候也会特意点到线代前后联…

TDengine 3.3.2.0 发布:新增 UDT 及 Oracle、SQL Server 数据接入

经过数月的开发和完善&#xff0c;TDengine 3.3.2.0 版本终于问世了。这一版本中既有针对开源社区的功能优化&#xff0c;也有从企业级用户需求出发做出的功能调整。在开源版本中&#xff0c;我们增强了系统的灵活性和兼容性&#xff1b;而在企业级版本中&#xff0c;新增了关键…

TK秘籍:深度剖析机房IP与住宅IP的利与弊

大家好&#xff0c;今天我们来聊聊TikTok运营中的一个重要环节——IP地址的选择。 想象一下&#xff0c;你在TikTok上发布视频&#xff0c;就像是在一个热闹的市集上摆摊&#xff0c;而IP地址就是你的摊位位置。选对了位置&#xff0c;你的摊位就能吸引更多顾客&#xff0c;也…

最小二乘求待定位点的位置(三维环境)|MATLAB

前言 之前发过三点法求待测点位置的程序讲解&#xff0c;哪个是二维的&#xff0c;见&#xff1a;基于伪逆的三点法距离求位置&#xff0c;MATLAB源代码&#xff08;MATLAB函数&#xff09; 这里给出三维情况下的函数和测试代码。对于函数&#xff0c;输入已知锚点的位置、待…

JavaEE:Spring Web简单小项目实践三(留言板实现)

学习目的&#xff1a; 1、理解前后端交互过程 2、学习接口传参&#xff0c;数据返回以及页面展示 目录 1、准备工作 2、约定前后端交互接口 1、获取全部留言 2、发表新留言 3、实现服务器端代码 4、调整前端页面代码 5、运行测试 1、准备工作 创建SpringBoot项目&#x…

Linux 服务器管理和维护

Linux 是一个非常严谨的操作系统&#xff0c;每个目录都有自己的作用&#xff0c;这些作用是固定的&#xff0c;没有特殊情况&#xff0c;应严格执行&#xff1b; Linux 中所有东西以文件形式存储和管理&#xff0c;命令也不例外&#xff1b; 以下四个 bin 是二进制文件&…

SVM 技能测试:25 个 MCQ 用于测试数据科学家的 SVM

SVM 技能测试:25 个 MCQ 用于测试数据科学家的 SVM(2024 年更新) 一、介绍 你可以把机器学习算法想象成一个装满斧头、剑和刀片的军械库。你有各种各样的工具,但你应该学会在正确的时间使用它们。打个比方,将“线性回归或逻辑回归”视为一把能够有效地切片和切块数据但…

鸿蒙仓颉语言【泛型generic】

泛型 泛型特性&#xff1a; 在给定的代码中&#xff0c;泛型被用于定义参数的类型。举例来说&#xff0c;Array和Array<(Event, (Event)->Event)>中的Array都是泛型类型&#xff0c;它们可以接受不同类型的参数。 与Java的泛型相比&#xff1a; Java也有泛型特性&am…

LeetCode 739, 82, 106

文章目录 739. 每日温度题目链接标签思路代码 82. 删除排序链表中的重复元素 II题目链接标签思路代码 106. 从中序与后序遍历序列构造二叉树题目链接标签思路二叉树的三种遍历值与索引的映射对于后序遍历的使用对于中序遍历的使用 代码 739. 每日温度 题目链接 739. 每日温度…

力扣第十八题——四数之和

内容介绍 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#xff09;&#xff1a; 0…

jenkins 插件版本冲突

一、Jenkins安装git parameter 插件重启后报错与临时解决方案 cd /root/.jenkins cp config.xml config.xml.bak vim config.xml <authorizationStrategy class"hudson.security.FullControlOnceLoggedInAuthorizationStrategy"><denyAnonymousReadAcces…

protoc-gen-go-http: program not found or is not executable

# 1 先升级到最新版 sudo kratos upgrade # 2 安装 protoc-gen-go-http go get -u github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2 go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2 # 3 安装 protoc-gen-go-errors go get -u github.com/go-…

【工具使用】EMACS的verilog_mode脚本

#工作记录# 俗话说不会玩连连看的工程师不是一个好的SoC工程师。 在做集成工作的时候&#xff0c;集成连线估计是一件比较繁琐且容易出错的事情&#xff0c;连线类型定义出错、位宽问题、连线众多等等问题&#xff0c;此时使用由Veripool带来的verilog_mode简直是令人神清气爽…

基于牛顿-拉夫逊优化算法(Newton-Raphson-based optimizer, NBRO)的无人机三维路径规划

牛顿-拉夫逊优化算法(Newton-Raphson-based optimizer, NBRO)是一种新型的元启发式算法&#xff08;智能优化算法&#xff09;&#xff0c;该成果由Sowmya等人于2024年2月发表在中科院2区Top SCI期刊《Engineering Applications of Artificial Intelligence》上。 1、算法原理…

制造运营管理系统(MOM系统),企业实现先进制造的关键一步

随着全球制造业的快速发展&#xff0c;企业对于生产效率和成本控制的要求日益增高。在这个背景下&#xff0c;制造运营管理系统&#xff08;MOM系统&#xff09;成为了企业提升竞争力的关键工具。盘古信息作为业内领先的智能制造解决方案提供商&#xff0c;其MOM系统更是以其卓…

首批通过 | 百度通过中国信通院H5端人脸识别安全能力评估工作

2024年5月&#xff0c;中国信息通信研究院人工智能研究所依托中国人工智能产业发展联盟安全治理委员会&#xff08;AIIA&#xff09;、“可信人脸应用守护计划”及多家企业代表共同开展《H5端人脸识别线上身份认证安全能力要求及评估方法》的编制工作&#xff0c;并基于该方法开…

大数据时代,如何用Scikit-Learn高效转换数据?

大数据时代&#xff0c;如何用Scikit-Learn高效转换数据&#xff1f; 在数据科学领域&#xff0c;数据预处理是至关重要的一步。Scikit-Learn&#xff08;简称sklearn&#xff09;&#xff0c;作为Python中最受欢迎的机器学习库之一&#xff0c;提供了一系列的数据转换工具&am…

COD论文笔记 Deep Gradient Learning for Efficient Camouflaged 2022

动机 这篇论文的动机在于解决伪装目标检测(COD)中的一个关键问题&#xff1a;在复杂背景下&#xff0c;伪装目标与背景的边界模糊&#xff0c;使得检测变得极其困难。现有的方法&#xff0c;如基于边界或不确定性的模型&#xff0c;通常仅响应于伪装目标的稀疏边缘&#xff0c…

DM数据库导出excel表结构

select utc.column_name 字段名, utc.data_type 字段类型, utc.data_length 数据长度, utc.data_precision 数据精度, utc.nullable 是否为空 , ucc.comments 备注 from user_tab_columns utc,user_col_comments ucc where utc.column_name ucc.column_name and utc.Table_Nam…