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