在JPA中处理Java的LocalDateTime

几天前,我在处理JPA中的LocalDateTime属性时遇到问题。 在这篇博客文章中,我将尝试创建一个示例问题来说明该问题以及我使用的解决方案。

考虑以下实体,该实体为特定公司的员工建模–

@Entity
@Getter
@Setter
public class Employee {@Id@GeneratedValueprivate Long id;private String name;private String department;private LocalDateTime joiningDate;
}

我使用的是Spring Data JPA,因此创建了以下存储库–

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {}

我想找到在特定日期加入公司的所有员工。 为此,我从
JpaSpecificationExecutor

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long>,JpaSpecificationExecutor<Employee> {}

并写了如下查询

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class EmployeeRepositoryIT {@Autowiredprivate EmployeeRepository employeeRepository;@Testpublic void findingEmployees_joiningDateIsZeroHour_found() {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime joiningDate = LocalDateTime.parse("2014-04-01 00:00:00", formatter);Employee employee = new Employee();employee.setName("Test Employee");employee.setDepartment("Test Department");employee.setJoiningDate(joiningDate);employeeRepository.save(employee);// Query to find employeesList<Employee> employees = employeeRepository.findAll((root, query, cb) ->cb.and(cb.greaterThanOrEqualTo(root.get(Employee_.joiningDate), joiningDate),cb.lessThan(root.get(Employee_.joiningDate), joiningDate.plusDays(1))));assertThat(employees).hasSize(1);}
}

以上测试顺利通过。 但是,以下测试失败了(应该通过了)–

@Test
public void findingEmployees_joiningDateIsNotZeroHour_found() {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime joiningDate = LocalDateTime.parse("2014-04-01 08:00:00", formatter);LocalDateTime zeroHour = LocalDateTime.parse("2014-04-01 00:00:00", formatter);Employee employee = new Employee();employee.setName("Test Employee");employee.setDepartment("Test Department");employee.setJoiningDate(joiningDate);employeeRepository.save(employee);List<Employee> employees = employeeRepository.findAll((root, query, cb) ->cb.and(cb.greaterThanOrEqualTo(root.get(Employee_.joiningDate), zeroHour),cb.lessThan(root.get(Employee_.joiningDate), zeroHour.plusDays(1))));assertThat(employees).hasSize(1);
}

与之前的测试唯一不同的是,在先前的测试中,我将零小时作为加入日期,而在这里,我使用了上午8点。 起初,我觉得很奇怪。 只要将员工的入职日期设置为一天的零小时,测试似乎就会通过,但是如果将其设置为其他时间,则测试会失败。
为了调查问题,我打开了休眠日志记录,以查看实际查询和发送到数据库的值,并在日志中注意到了类似的内容–

2017-03-05 22:26:20.804 DEBUG 8098 --- [           main] org.hibernate.SQL:selectemployee0_.id as id1_0_,employee0_.department as departme2_0_,employee0_.joining_date as joining_3_0_,employee0_.name as name4_0_fromemployee employee0_whereemployee0_.joining_date>=?and employee0_.joining_dateHibernate:selectemployee0_.id as id1_0_,employee0_.department as departme2_0_,employee0_.joining_date as joining_3_0_,employee0_.name as name4_0_fromemployee employee0_whereemployee0_.joining_date>=?and employee0_.joining_date2017-03-05 22:26:20.806 TRACE 8098 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARBINARY] - [2014-04-01T00:00]2017-03-05 22:26:20.807 TRACE 8098 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARBINARY] - [2014-04-02T00:00]

显然,JPA 并未joinDate属性视为日期或时间,而是视为VARBINARY类型。 这就是与实际日期比较失败的原因。

我认为这不是一个很好的设计。 它没有抛出UnsupportedAttributeException之类的东西,而是默默地尝试将值转换为其他值,从而使比较失败是随机的(不是完全随机的)。 除非您有很强的自动化测试套件,否则在应用程序中很难找到这种类型的错误,幸运的是,我的情况如此。

现在回到问题。 JPA无法正确转换LocalDateTime的原因非常简单。 JPA规范的最新版本(2.1)在Java 8之前发布,因此它不能处理新的Date and Time API。

为了解决该问题,我创建了一个自定义转换器实现,该实现将LocalDateTime转换为
将java.sql.Timestamp保存到数据库之前,反之亦然。 那解决了问题–

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {@Overridepublic Timestamp convertToDatabaseColumn(LocalDateTime localDateTime) {return Optional.ofNullable(localDateTime).map(Timestamp::valueOf).orElse(null);}@Overridepublic LocalDateTime convertToEntityAttribute(Timestamp timestamp) {return Optional.ofNullable(timestamp).map(Timestamp::toLocalDateTime).orElse(null);}
}

每当我尝试保存LocalDateTime属性时,上述转换器将自动应用。 我还可以使用来显式标记要显式转换的属性
javax.persistence.Convert注释–

@Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime joiningDate;

完整的代码可以在Github上找到 。

翻译自: https://www.javacodegeeks.com/2017/03/dealing-javas-localdatetime-jpa.html

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

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

相关文章

Junit4 简单教程

一、环境搭建 对于习惯使用Eclipse开发平台来说&#xff0c;Junit早已是非常通常的插件&#xff0c;在Eclipse开发平台中&#xff0c;可以非常方便地搭建Junit测试环境。 1、在Eclipse上创建工程&#xff0c;任何Java工程都行。 2、引入Junit的libraries库&#xff0c;选用Juni…

Qt显示中文的方法

QT 显示中文的三种方法 最近在用Qt做项目&#xff0c;遇到UI不能显示中文的问题&#xff0c;发现有3种方法可以解决&#xff0c;先记录一下 方法一 QString::fromLocal8Bit("你好中国")1 方法二 QStringLiteral("你好中国")1 方法三 在.…

python中exception类的_面试题 | 列举几个Python中的标准异常类?

【摘要】今天给大家解答一道Python常见的面试题&#xff0c;希望这个面试栏目&#xff0c;给那些准备面试的同学&#xff0c;提供一点点帮助!小编会从最基础的面试题开始&#xff0c;每天一题。如果参考答案不够好&#xff0c;或者有错误的话&#xff0c;麻烦大家可以在留言区给…

jsonp和CORS跨域实现

一、jsonp&#xff0c;使用jquery封装的$.ajax&#xff0c;返回数据类型要设置为jsonp 示例&#xff1a; $.ajax({type: get,contentType: "application/json; charsetutf-8",url: "http://localhost:8080/aqi/getCityList.php",dataType: jsonp,< /spa…

Qt数字与字符串之间的相互转换

把QString转换为 double类型方法1.QString str"123.45";double valstr.toDouble(); //val123.45方法2.很适合科学计数法形式转换bool ok;double d;dQString("1234.56e-02").toDouble(&ok); //oktrue;d;12.3456.把QString转换为float形1.QString str&qu…

无线ap软件_无线WIFI网络干扰优化,不懂必看!新手在家里也能用的网络知识

由于国家频谱资源分配中保留一些频段用于工业、科研、医疗等方面应用&#xff0c;即ISM频段&#xff0c;如2.400到2.483G和5.170到5.825G。使用这些频段都无需许可证&#xff0c;只需要遵守一定的发射功率任何厂家都可以使用&#xff0c;WLAN也采用ISM频段。随着WLAN技术在企业…

postgresql 比较两个时间差大于 N个小时

摘要: PG 中时间想减后为interval &#xff0c;比较两个时间大于某个小时或者分钟等可以直接通过interval来实现 example1&#xff1a; -- 判断两个时间差大于4个小时 select timestamp 2013-11-11 10:00:00 - timestamp 2013-11-08 12:00:00 > interval 4 hour; examp…

spring mvc重定向_Spring的Web MVC –重定向到内存泄漏

spring mvc重定向他们说一块岩石会引起雪崩。 最近&#xff0c;我的一位同事Marcin Radoszewski给了我一块岩石。 您可能永远不会猜到它是什么&#xff0c;但是有机会在许多Web应用程序中使用它。 请允许我向您介绍这块石头。 您可能很清楚发布模式后的重定向 。 使用Spring F…

关闭8080端口

转载于:https://www.cnblogs.com/Health-zhang/p/10775034.html

Qt 布局(水平、垂直、网格)

开发一个图形界面应用程序&#xff0c;界面的布局影响到界面的美观。在设计一个界面之前&#xff0c;应该考虑到开发的界面可能给不用的用户使用&#xff0c;而用户的屏幕大小、纵横比例、分辨率可能不同&#xff0c;界面还可能是可缩放的&#xff0c;程序应该可以适应这些变化…

JSR 365更新:深入CDI 2.0

上下文和依赖注入2.0&#xff08; JSR 365 &#xff09;是CDI 1.2的更新&#xff0c;CDI 1.2目前是Java EE 7平台的一部分。 目前处于公开审查阶段 。 对于不熟悉CDI的那些人&#xff0c;它定义了一组功能强大的免费服务&#xff0c;这些服务可充当凝胶&#xff0c;帮助改善应用…

postgres复制表结构

复制表结构 12create table his_process_data_201405 as( select * from his_process_data_201406 limit 0)完整复制一张表 12create table his_process_data_201405 as( select * from his_process_data_201406)

Django 数据导入和导出

一&#xff0c;简单的数据导出与导入&#xff08;简单的迁移&#xff09; 1. django 项目提供了一个导出的方法 python manage.py dumpdata, 不指定 appname 时默认为导出所有的app 1python manage.py dumpdata [appname] > appname_data.json比如我们有一个项目叫 mysite, …

cifar-10 图像转为jpg

dir_file目录下需有这几个文件 源代码 #codingutf-8 import cv2 import numpy as np import os#文件夹名 str_2 ./train_cifar10 str_1 ./test_cifar10#判断文件夹是否存在&#xff0c;不存在的话创建文件夹 if os.path.exists(str_1) False: os.mkdir(str_1) if os.path.e…

python3小游戏源代码_Python3制作仿“FlappyBird”小游戏|python3教程|python入门|python教程...

https://www.xin3721.com/eschool/pythonxin3721/ 本文转载至知乎ID&#xff1a;Charles&#xff08;白露未晞&#xff09;知乎个人专栏 下载W3Cschool手机App&#xff0c;0基础随时随地学编程>>戳此了解 导语 本期我们将制作一个仿“经典90坦克大战”的小游戏。啊&#…

java java编码_Java编码约定被认为是有害的

java java编码在Oracle网站上有Java编程语言的官方代码约定指南。 您可能希望这份超过20页的文档将是有关Java语言的最佳实践&#xff0c;提示和技巧的最完整&#xff0c;最全面和最权威的来源。 但是一旦您开始阅读它&#xff0c;失望和沮丧和愤怒就会增加。 我想指出本指南中…

PostgreSQL数据库修改sql表的方法汇总

一&#xff0c;修改表 PostgreSQL 提供了一族命令用于修改现有表。 可以实现&#xff1a; 增加字段&#xff0c; 删除字段&#xff0c; 增加约束&#xff0c; 删除约束&#xff0c; 修改默认值&#xff0c; 重命名字段&#xff0c; 重命名表。 这些操作可以用&#xff1a;ALTE…

混淆矩阵怎么看_201.工具篇MECE法则:透过结构看世界。

工具篇|战略工具1之前讲过了商业、管理、个人&#xff0c;今天讲如何用工具来提高上述的效率工具。今天先讲一MECE法则。某公司将2020年定为品牌战略年&#xff0c;小王接到领导安排写作任务&#xff0c;要求充分阐述公司 的品牌主张。小张憋了半天&#xff0c;稿子交了上去。领…

nRFgo Studio 和 Nrfjprog 无法找到JLinkARM.dll的解决方法

本文转自&#xff1a;https://www.lotlab.org/2017/09/12/nrfgo-studio-and-nrfjprog-could-not-find-jlinkarm-dll/ Segger在第一次安装的时候&#xff0c;会在注册表中添加安装路径的字段&#xff0c;nRF的两个软件就根据这两个注册表字段来寻找JLinkARM.dll。而当你卸载/更新…

mnist数据集图片提取出来

# -*- coding: UTF-8 -*-# 把mnist数据集转成图片做测试&#xff0c;图片更为通用import cv2 import os from keras.datasets import mnistimport numpy as np str_1 mnisttrain str_2 mnisttest if os.path.exists(str_1):os.mkdir(str_1)if os.path.exists(str_2):os.mkdir…