[英]Why is the following Thymeleaf template processing not working? (SpringBoot, Thymeleaf)
我正在尝试为我从服务器发回的book
li
中的Set<Review> reviews
中的每个review
创建一个ul
。 结果似乎是一个巨大的内部服务器错误,我得到一个很长的堆栈跟踪打印到终端,我不知道可能是什么问题。 如果我注释掉ul
块,一切正常。
错误(打开新链接,pastebin) (不是完整的错误,它不适合 VSCODE 终端。
book.html
<div class="container" style="width: 100%; padding-top: 25px; display: flex; justify-content: center;">
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="..." alt="Card image cap">
<div class="card-body">
<h5 th:text="${book.name}" class="card-title">Book name here.</h5>
<p th:text="${book.author}" class="card-text">Author name here.</p>
<p th:text="${book.isbn}" class="card-text">ISBN number here.</p>
</div>
<ul class="list-group list-group-flush">
<li th:each="review : ${book.reviews}" th:text="${review.review}" class="list-group-item">Review goes here.</li>
</ul>
</div>
</div>
BookController.java
package com.domain.congregentur.book;
import ...
@Controller
@RequestMapping("api/books")
public class BookController {
public BookService bookService;
@Autowired
public BookController(BookService bookService) {
this.bookService = bookService;
}
...
@GetMapping("/{id}")
public String find(@PathVariable("id") Long id, Model model) {
Optional<Book> book = bookService.findById(id);
if (book.isPresent()) {
model.addAttribute("book", book.get());
return "book";
}
return "books";
}
...
}
Book.java
package com.domain.congregentur.book;
import ...
@Entity
@Table(name = "Books")
@EqualsAndHashCode
@ToString
@Getter
@Setter
public class Book implements Serializable {
@Id
@SequenceGenerator(name = "book_sequence", sequenceName = "book_sequence", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_sequence")
private Long id;
@NotNull
private String isbn;
@NotNull
private String name;
@NotNull
private String author;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "book")
private Set<Review> reviews;
Book() {
}
public Book(Long id, String isbn, String name, String author) {
this.id = id;
this.isbn = isbn;
this.name = name;
this.author = author;
}
public Book(String isbn, String name, String author) {
this.isbn = isbn;
this.name = name;
this.author = author;
}
public Book updateWith(Book book) {
return new Book(
this.id,
book.isbn,
book.name,
book.author);
}
}
Review.java
package com.domain.congregentur.review;
import ...
@Entity
@Table(name = "Reviews")
@EqualsAndHashCode
@ToString
@Setter
@Getter
public class Review {
@Id
@SequenceGenerator(name = "review_sequence", sequenceName = "review_sequence", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "review_sequence")
private Long id;
@NotNull
private String review;
@ManyToOne
@JoinColumn(name = "isbn", referencedColumnName = "isbn")
private Book book;
Review() {
}
public Review(String review, Book book) {
this.review = review;
this.book = book;
}
}
可能值得一提的是,这是我将一些随机测试数据实例化到我的数据库以进行测试的方式,我不知道这是否是一种合适的方法,它可能与问题相关,也可能不相关。 随时教育我。
DataLoader.java
package com.domain.congregentur.dataloader;
import ...
@Component
public class DataLoader implements ApplicationRunner {
private BookRepository bookRepository;
private ReviewRepository reviewRepository;
@Autowired
public DataLoader(BookRepository bookRepository, ReviewRepository reviewRepository) {
this.bookRepository = bookRepository;
this.reviewRepository = reviewRepository;
}
public void run(ApplicationArguments args) {
Book b1 = new Book("9780812969641", "In Search of Lost Time", "Marcel Proust");
Book b2 = new Book("9781772267143", "Swann's Way", "Marcel Proust");
Book b3 = new Book("9780099469698", "Don Quixote", "Miguel de Cervantes");
bookRepository.saveAll(List.of(b1, b2, b3));
List<Review> reviews = List.of(
new Review("Book1 -> Review1", b1),
new Review("Book1 -> Review2", b1),
new Review("Book2 -> Review1", b2),
new Review("Book2 -> Review2", b2),
new Review("Book3 -> Review1", b3),
new Review("Book3 -> Review2", b3));
reviewRepository.saveAll(reviews);
}
}
编辑:在查看了堆栈跟踪之后,它似乎在重复以下部分,但在某些特定位置略有不同的数字。
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:591) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:458) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at com.domain.congregentur.book.Book.hashCode(Book.java:26) ~[classes/:na]
at com.domain.congregentur.review.Review.hashCode(Review.java:22) ~[classes/:na]
at java.base/java.util.HashMap.hash(HashMap.java:340) ~[na:na]
at java.base/java.util.HashMap.put(HashMap.java:608) ~[na:na]
at java.base/java.util.HashSet.add(HashSet.java:220) ~[na:na]
at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:352) ~[na:na]
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:355) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:239) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:224) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:198) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:232) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:190) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:96) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:105) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:87) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:705) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:76) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2203) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:595) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
这是因为您使用的是@EqualsAndHashCode
Lombok 注释。 获取 Review JPA 实体的哈希码时出现错误(可能是递归的,因为您的堆栈跟踪很大,我不确定)。
Review 实体中 Lombok 自动生成的 hashcode 方法将调用 Book 实体,该实体尝试获取评论集的 hashcode。 此 Set 需要先初始化,然后才能读取。
at com.domain.congregentur.book.Book.hashCode(Book.java:26) ~[classes/:na]
at com.domain.congregentur.review.Review.hashCode(Review.java:22) ~[classes/:na]
您可以使用 2 个选项来解决此问题。
这是一篇很好的文章,解释得很详细。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.