简体   繁体   English

如何在 JPA 和 Hibernate 中使用 JoinColumn 对实体执行 upsert

[英]How to perform an upsert on entity with JoinColumn in JPA and Hibernate

Fairly new to the hibernate-core integrate with JPA.与 JPA 集成的休眠内核相当新。 Our entities look like我们的实体看起来像

@MappedSuperclass
abstract class BasicEntity {

    @Id
    @GenericGenerator(name="uuid",strategy="uuid")
    @GeneratedValue(generator="uuid")
    private String id;

}

@Entity
@Table(name = "book")
class Book extends BasicEntity { 
    @ManyToOne
    @JoinColumn(name="book_genre")
    Genre genre

    @Column(name="texture")
    String texture;
}

@Data //lombok
@Entity
@Table(name="user_book_mapping")
class UserBookMapping extends BasicEntity {
    @ManyToOne
    @JoinColumn(name = "book_id")
    private Book book;
    
    @Column(name="user_id")
    String user_id;
}

What I am trying to perform is for every book read by a user, upsert (a book can be read twice by the same user) the UserBookMapping table.我要执行的是对于用户阅读的每一本书, UserBookMapping upsert (同一用户可以阅读一本书两次)。 Request object includes an array of user and books [{userId, bookId}] attributes for me to process.请求 object 包含一组用户和书籍[{userId, bookId}]属性供我处理。

Currently I am stuck with a solution where I am ending up fetching the Book entity from the primary table first, then fetching if such a row already exists with a combination of userId+bookId and then creating a new instance of UserBookMapping to write it to the database.目前我遇到了一个解决方案,我首先从主表中获取Book实体,然后使用userId+bookId的组合获取这样的行是否已经存在,然后创建一个新的UserBookMapping实例将其写入数据库。

This doesn't look optimized in any sense to me.在我看来,这在任何意义上都没有优化。 Theoretically(and in the NoSql world), what should be sufficient for me to do all of this would be to ensure valid bookIds are requested ( EXISTS ) and then perform an UPSERT for the UserBookMapping .从理论上讲(在 NoSql 世界中),我要做的就是确保请求有效的bookIdsEXISTS ),然后为UserBookMapping执行UPSERT But I am puzzled with both the ways to write and to formulate the data as java objects while computing.但是我对在计算时将数据编写和公式化为 java 对象的方式感到困惑。

Q1. Q1。 Do I really need to construct the Book entity?我真的需要构造Book实体吗?

Q2. Q2。 What is the clean way to do what I am trying to achieve?做我想要实现的目标的干净方法是什么?

As was suggested by @crizzis, you can do something like this:正如@crizzis 所建议的,您可以执行以下操作:

Book book = entityManager.getReference(Book.class, bookId);
Long booksPerUserCount = entityManager.createQuery(
    "select count(bu) from UserBookMapping bu where bu.book = :book and bu.user_id = :userId",
 Long.class )
.setParameter("book", book)
.setParameter("userId", userId)
.getSingleResult(); 

if (booksPerUserCount > 0) {
   UserBookMapping userBook = new UserBookMapping();
   userBook.setBook(book);
   userBook.setUserId(userId);
   entityManager.persist(userBook);
}

But it will work only if you know for sure that a book with id bookId exists.但只有当您确定存在 ID bookId的书时,它才会起作用。 You can read about entityManager.getReference() in hibernate documentation .您可以在hibernate 文档中阅读有关entityManager.getReference()的信息。

Please also note that this is not good idea to use @Data lombok annotation in hibernate/jpa entity, see for example this article .另请注意,在 hibernate/jpa 实体中使用@Data lombok 批注并不是一个好主意,请参见例如这篇文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM