【问题标题】:How to correctly save entity with @ManyToMany in Spring Boot?如何在 Spring Boot 中使用 @ManyToMany 正确保存实体?
【发布时间】:2021-01-15 22:39:20
【问题描述】:

我知道如何在纯 Hibernate 中使用 @ManyToMany 关系来持久化实体。但是如何在 Spring 中正确地做到这一点呢?

在休眠状态下:

EntityManager em = getEntityManager();
em.getTransaction.begin();

Book book = new Book("title", "isbn");
Category category = new Category("horror");

category.addBook(book);

em.persist(book);

em.getTransaction().commit();
em.getTransaction().close();

类似的东西。但是 Spring 呢,假设我有 @Service 从 @RestController 接收 Book 或 BookDto。

public void saveBook(Book book) {
    //what now
}

我应该在这里做什么,bookRepository.save(book); 是否足以保存这个 @ManyToMany 关系?我不需要 addBook、addCategory、removeBook 等其他方法吗?

提前谢谢你。

【问题讨论】:

  • 试试@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)

标签: java spring hibernate jpa spring-data


【解决方案1】:

Spring 的存储库只是包装 entityManager 并执行它的 persist 方法。你可以看看default implementation

这就是为什么“纯休眠”中的任何可能都可以通过带有几个注释的 Spring 存储库实现

注意 1 使用 spring,您很可能会用 @Transactional 注释替换事务样板,这就是为什么您需要小心在方法之间传递的实体。

注2你所说的“纯休眠”代码实际上是“纯JPA”,没有提到休眠。 hibernate 可能是您的 JPA 实现。

【讨论】:

  • 所以我必须在我的 JPQL 查询中写下这个,还是可以保持原样?注1:是的,我知道,注2:请原谅我在技术上不准确:P
  • 对于您提到的示例 bookRepository.save 将执行完全相同的操作。否则,您始终可以将 entityManager 注入您的存储库并在默认值不起作用时执行一些自定义逻辑。
【解决方案2】:

使用 Spring Boot 处理实体状态管理的标准方法是:

  1. 创建带有 @Entity 注释的实体类(我想你已经这样做了) - 例如 Book.class 实体;
  2. 创建扩展 JPARepository 的存储库接口,其中 T 是您的实体类(为 Book 创建一个,为 Category 创建另一个),ID 是您的实体类的主键。这将为您提供许多有用的存储库方法的默认实现的优势,例如 save()、findOneById() 等;
public interface BookRepository extends JPARepository<Book, Long> {}

假设您已将 Long 设置为图书实体的主键;

  1. 在服务类中注入存储库;

  2. 现在您可以像这样使用您的服务类和方法:

@RequiredArgsConstructor
@Service
public class BookService {

private final BookRepository bookRepository;

@Transactional
public void saveBook() {

   // just copying the logic from your question
   // but normally You would pass it as an argument to the method
    Book book = new Book("title", "isbn");
    Category category = new Category("horror");
    category.addBook(book);
    bookRepository.save(book);

    }
}

回答您的第二个问题 - 是的,您必须注意保持两个实体的关系同步,这里没有任何办法。因此,在@ManyToMany 关系中,您必须将类别添加到图书类别集合中,反之亦然。

【讨论】:

  • 谢谢!我昨天已经这样做了,但这是一个很好的答案,它应该存在于未来这样的问题中。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 2018-01-13
  • 2021-08-18
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多