簡體   English   中英

Hibernate/JPA/Spring 持久化(排序)集合的問題

[英]Hibernate/JPA/Spring Problems with persisting (sorted) collection

本來我想把這個寫成一個問題,但是在寫這篇文章時,我找到了一個解決方案。 如果這里有人有更好的,因為我的有點丑,請隨時發布。 否則,我只會將我的解決方案存檔在這里,以便其他面臨類似問題的人知道。 (解決方案可以在底部找到。)

我有以下需求需要滿足:

  • 在網頁上用復選框顯示所有“模塊”
  • 按彼此的兩個子集對模塊進行排序:
    1. 顯示在頂部的子集:所有被選中並因此保存在信息實體的“模塊”集合中的模塊
    2. 下面顯示的子集:所有尚未選擇的模塊(ID>0),直接從數據庫中檢索
  • 按字母順序對每個子集進行排序(不區分大小寫)

結果應如下所示:

[x] aaaModule
[x] AbbModule
[x] aBcModule
[ ] aabModule
[ ] acbModule

請注意,排序需要不區分大小寫,這就是 @OrderBy 不剪切的原因。 相反,我實現了要排序的實體類的 Comparable 接口,並在 @ManyToMany 映射上使用了 Hibernate 的 @SortNatural-Annotation。

我目前的解決方案(當然是簡化的)如下所示:

在 Information.java 實體中:

@ManyToMany
@JoinTable(
    name = "bla_modules", 
    schema = "blaSchema",
    joinColumns = { @JoinColumn(name = "bla_info_id") }, 
    inverseJoinColumns = { @JoinColumn(name = "bla_module_id") }
)
@SortNatural
private Set<Module> modules = new TreeSet<>();

在 Controller.java 中(在 GET-Mapping 中):

Set<Module> modulesToDisplay = new LinkedHashSet<>();
modulesToDisplay.addAll(currentInformation.getModules());
modulesToDisplay.addAll(moduleRepository.findByIdGreaterThanOrderByLabelAsc(0));
model.addAttribute("modulesToDisplay", modulesToDisplay);

在 info.jsp 里面:

<form:form method="POST" action="/informations.bla/editInformation" modelAttribute="currentInformation">
    <ul style="list-style-type:none">
        <c:forEach items="${modulesToDisplay}" var="module">
            <li>
                <div class="inline">
                    <form:checkbox path="modules" value="${module}" label="[${module.shortLabel}] ${module.label}"/>
                </div>
            </li>
        </c:forEach>
    </ul>
    <input type="submit" value="Save">
</form:form>

在 Controller.java 中(POST-Mapping):

public String editInformation(@ModelAttribute Information submittedInformation) {
    Information informationAfterSaving = informationRepository.save(submittedInformation);

在我在集合上使用 @SortNatural 注釋之前,這一切都很好,但在這種情況下,JPA 在從數據庫加載 TreeSet 時沒有對 TreeSet 進行排序。

如果我從數據庫加載現有的信息實體,顯示它,更改屬性,然后將其保存回來,它仍然可以很好地工作。

但是,當我加載一個新的信息實體時,它剛剛通過“新信息()”在控制器中創建,當 GET-Mapping 沒有收到要加載的有效 ID 時,我突然收到錯誤java.lang.ClassCastException: class java.util.LinkedHashSet cannot be cast to class java.util.SortedSetInformation informationAfterSaving = informationRepository.save(submittedInformation);java.lang.ClassCastException: class java.util.LinkedHashSet cannot be cast to class java.util.SortedSet Information informationAfterSaving = informationRepository.save(submittedInformation); 在控制器的 POST-Mapping 中執行。

解決方案可以在下面我自己的答案中找到。 我希望有一天它可以幫助某人。

再見

解決方案

在調用 Repository 的 .save 方法之前,在 Controller 的 POST-Mapping 中,只需執行以下操作:

submittedInformation.setModules(new TreeSet<Module>(submittedInformation.getModules()));

現在我覺得有點愚蠢,因為我之前沒有想到這個明顯的解決方案,不會撒謊。

不過,該解決方案仍然有點難看,所以如果有人知道如何告訴 JPA/Hibernate 將接收到的 Spring 集合正確地轉換回 TreeSet,或者告訴 Spring 以 TreeSet 的形式附加 Checkbox-Collection,那么請告訴我。

選擇

對我來說不是一個合適的解決方案,但@MartinFrey 也提供了一個可能的解決方案:只需跳過后端的排序,而是在 GUI 端排序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM