本文介紹了Spring數據存儲庫:帶順序的Find&Quot;方法獲得錯誤的順序的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我有一個帶有一些JPA存儲庫的Spring Boot應用程序。
我在其中一個存儲庫接口中定義了以下方法:
public List<Post> findAllByOrderByPublishedOnDesc();
很明顯,我想檢索按publishOn
DESC排序的所有Post
的列表。奇怪的是,當兩個或更多帖子的值publishedOn
只與LocalDateTime類的分鐘組件不同時,我會得到錯誤的順序(請參見下面代碼中的注釋)。
我做錯了什么?
以下是示例代碼。使用h2數據庫執行測試:
實體:
@Entity
public class Post
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
@Column(unique = true, nullable = false)
String sourceUrl;
@Column
String title;
@Column
LocalDateTime publishedOn;
@LastModifiedDate
LocalDateTime editedOn;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
Text text;
}
存儲庫:
public interface PostRepository extends JpaRepository<Post, Long>
{
public Post findBySourceUrl(String sourceUrl);
public List<Post> findAllByOrderByPublishedOnDesc();
}
測試:
public class OrderByJPATest
{
@Autowired
PostRepository postRepo;
public OrderByJPATest()
{
}
@Test
public void testOrderByDays()
{
// First try: older by 1 day
Post newer = insertTestEntity("newer", LocalDateTime.of(2016, 11, 13, 0, 0));
Post older = insertTestEntity("older", LocalDateTime.of(2016, 11, 12, 0, 0));
List<Post> ordered = postRepo.findAllByOrderByPublishedOnDesc();
ordered.stream().forEach((post) -> log.info("{} => {}", post.getSourceUrl(), post.getPublishedOn()));
/*
output:
newer => 2016-11-13T00:00
older => 2016-11-12T00:00
*/
assertTrue(ordered.get(0).getPublishedOn()
.isAfter(ordered.get(1).getPublishedOn()));
postRepo.deleteAll();
postRepo.flush();
// Second try: older by 1 minute
newer = insertTestEntity("newerBy1Min", LocalDateTime.of(2016, 11, 13, 01, 02));
older = insertTestEntity("olderBy1Min", LocalDateTime.of(2016, 11, 13, 01, 01));
ordered = postRepo.findAllByOrderByPublishedOnDesc();
ordered.stream().forEach((post) -> log.info("{} => {}", post.getSourceUrl(), post.getPublishedOn()));
/*
output:
olderBy1Min => 2016-11-13T01:01
newerBy1Min => 2016-11-13T01:02
*/
// this assert fails!
assertTrue(ordered.get(0).getPublishedOn()
.isAfter(ordered.get(1).getPublishedOn()));
}
private Post insertTestEntity(String url, LocalDateTime publishDate)
{
Text text = new Text();
text.setValue("Testing...");
Post post = new Post();
post.setPublishedOn(publishDate);
post.setSourceUrl(url);
post.setText(text);
return postRepo.save(post);
}
}
POM(依賴項):
<dependencies>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.6.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!--Additional dependencies -end-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
推薦答案
jpa默認情況下會將Java的LocalDateTime
映射到BLOB
,而不是DateTime
或Timestamp
。
數據庫無法理解如何對Blob執行日期/時間排序。
-
確保使用適當的數據類型創建架構(使用
@Column
批注或使用SQL腳本)。將
hibernate-java8
依賴項添加到您的項目
執行上述步驟后,將進行正確的排序。
這篇關于Spring數據存儲庫:帶順序的Find&Quot;方法獲得錯誤的順序的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,