Spring JPA поле денормализованного счетчика один ко многим
У меня есть две сущности, Книги и Комментарии, в отношениях один ко многим (одна книга может иметь много комментариев). Я хочу быть в состоянии перечислить книги и количество комментариев о книге. Я хочу, чтобы он был денормализован, то есть у сущности books будет счетчик с количеством комментариев к этой книге, и он будет обновляться каждый раз при вводе комментария (просто игра с концепцией, нет необходимости обсуждать необходимость денормализации здесь).).
Я думаю (поправьте меня, если я ошибаюсь) это можно легко сделать с помощью триггера в базе данных (когда создается новый комментарий, обновите счетчик в таблице книг до соответствующего bookId), но ради обучения я хочу сделать это через JPA, если это имеет смысл.
Что я до сих пор: // опущены некоторые аннотации, просто общая информация
Бокс сущность:
@Entity
public class Books {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String author;
private Long numComments;
// getters and setters...
}
Комментарии объекта:
@Entity
public class Comments {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String comment;
private Long authorId;
private Long bookId;
// getters and setters...
}
Репозиторий книг: я добавил сюда запрос для выполнения обновления
/**
* Spring Data JPA repository for the Books entity.
*/
public interface BooksRepository extends JpaRepository<Books,Long> {
@Modifying
@Query("UPDATE Books v SET v.numComments = v.numComments + 1 WHERE v.id = :bookId")
int updateCounter(@Param("bookId")Long bookId);
}
А теперь вопрос: что дальше? Я думаю, что могу поместить обновление сущности Books, аннотирующее с помощью @PostPersist метод сущности Comments, но пока я потерпел неудачу. Я могу представить что-то вроде этого:
@PostPersist //This function in the entity Comments
protected void updateBooks() {
//Likely some call to the repository here that updates the count
// in books the info we have from current entity.
}
Есть идеи, как это сделать? Некоторые лучшие практики об этом виде денормализации в JPA? Лучше использовать триггеры базы данных?
1 ответ
Весной не управлял вашими сущностями, и ваша идея возможна, но вы должны ввести BooksRepository
в энтти класс тогда останься у тебя нольпоинтерекс, потому что весной не успел энтай классы, причина твоя BooksRepository
не инициализировано, попробуйте также прочитать этот пост Инъекция Бина в класс сущности JPA @Entity и anotate @Configurable
после
попробуй это
@PostPersist
protected void updateBooks(Comments comment) {
int totalComment = BooksRepository.updateCounter(comment.getBookId());
System.out.println(totalComment); // see totalComment in console
}
но хороший упор в классах обслуживания после звонка updateCounter
когда вставить комментарий
пример в вашем CommendService: когда вы пытаетесь вставить вставку Commend после вызова вашего updateCounter
if(comment.getBookId() != null) //Simple Control
{
CommentRepository.save(comment);
BooksRepository.updateCounter(comment.getBookId());
}