日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

在JPA中处理Java的LocalDateTime

發布時間:2023/12/3 java 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在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

總結

以上是生活随笔為你收集整理的在JPA中处理Java的LocalDateTime的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。