1.概述
在本快速教程中,我们将学习如何在JPA对象上执行INSERT语句。
有关总体上有关Hibernate的更多信息,请查看我们的Spring JPA综合指南和JPA Spring Data简介,以深入研究该主题。
2.在JPA中保留对象
在JPA中,从瞬态到托管状态的每个实体都由EntityManager自动处理。
EntityManager检查给定的实体是否已经存在,然后决定是否应插入或更新该实体。由于这种自动管理,JPA允许的唯一语句是SELECT,UPDATE和DELETE。
在下面的示例中,我们将研究管理和绕过此限制的不同方法。
3.定义通用模型
现在,让我们开始定义一个简单的实体,我们将在本教程中使用它:
1 |
@Entity @Id // standard getters and setters, default and all-args constructors |
另外,让我们定义一个用于实现的存储库类:
1 |
@Repository @PersistenceContext } |
另外,我们将应用@Transactional批注来由Spring自动处理事务。这样,我们就不必担心使用ourEntityManager创建事务,提交更改或在发生异常情况下手动执行回滚。
4.createNativeQuery
对于手动创建的查询,我们可以使用EntityManager#createNativeQuery方法。它允许我们创建任何类型的SQL查询,而不仅仅是JPA支持的查询。让我们向存储库类添加一个新方法:
1 |
@Transactional |
使用这种方法,我们需要定义一个包含列名的文字查询并设置它们的相应值。
现在我们可以测试我们的存储库:
1 |
@Test assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> { |
在我们的测试中,每个操作都尝试将新条目插入我们的数据库。由于我们尝试插入具有相同ID的两个实体,因此第二个插入操作会因抛出aPersistenceException而失败。
如果我们使用Spring Data的@Query,这里的原理是相同的。
5.坚持
在前面的示例中,我们创建了插入查询,但是必须为每个实体创建文字查询。这种方法不是很有效,并且会导致大量样板代码。
相反,我们可以使用来自EntityManager的持久方法。
与之前的示例一样,让我们??使用自定义方法扩展存储库类:
1 |
@Transactional |
现在,我们可以再次测试我们的方法:
1 |
@Test |
与使用本机查询相反,我们不必指定列名和相应的值。而是由EntityManager为我们处理。
在上面的测试中,我们还希望抛出EntityExistsException而不是它的superclassPersistenceException,它是由persist更为专门化和抛出的。
另一方面,在此示例中,我们必须确保每次使用新的Person实例调用插入方法,否则它将已经由EntityManager管理,从而导致更新操作。
六,结论
在本文中,我们说明了对JPA对象执行插入操作的方法。我们查看了使用本机查询以及使用EntityManager#persist创建自定义INSERT语句的示例。