1. Introduction
1.绪论
Spring Data JPA allows us to define derived methods that read, update or delete records from the database. This is very helpful as it reduces the boilerplate code from the data access layer.
Spring Data JPA 允许我们定义衍生方法,以便从数据库读取、更新或删除记录。这非常有帮助,因为它减少了数据访问层的模板代码。
In this tutorial, we’ll focus on defining and using Spring Data derived delete methods with practical code examples.
在本教程中,我们将通过实际的代码示例,重点介绍定义和使用Spring Data衍生的删除方法。
2. Derived deleteBy Methods
2.派生的deleteBy方法
First, let’s set up our example. We’ll define a Fruit entity to save the name and color of items available in a fruit store:
首先,让我们来设置我们的例子。我们将定义一个Fruit实体,以保存水果店中可用物品的名称和颜色。
@Entity
public class Fruit {
@Id
private long id;
private String name;
private String color;
// standard getters and setters
}
Next, we’ll add our repository to operate on Fruit entities, by extending the JpaRepository interface and adding our derived methods to this class.
接下来,我们将通过扩展JpaRepository接口,并将我们的派生方法添加到这个类中,来增加我们的存储库对Fruit实体的操作。
Derived methods can be defined as VERB + attribute defined in an entity. A few of the allowed verbs are findBy, deleteBy, and removeBy.
衍生方法可以被定义为VERB+实体中定义的属性。允许的几个动词是findBy、deleteBy、和removeBy。
Let’s derive a method to delete Fruits by their name:
让我们派生出一个方法,按其名称删除水果s。
@Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
Long deleteByName(String name);
}
In this example, the deleteByName method returns the count of deleted records.
在这个例子中,deleteByName方法返回删除记录的数量。
Similarly, we can also derive a delete method of the form:
同样地,我们也可以派生出一个delete方法,其形式为:。
List<Fruit> deleteByColor(String color);
Here, the deleteByColor method deletes all fruits with a given color and returns a list of deleted records.
在这里,deleteByColor方法删除了所有具有给定颜色的水果,并返回一个删除记录的列表。
Let’s test the derived delete methods. First, we’ll insert a few records in the Fruit table, by defining the data in test-fruit-data.sql:
让我们测试一下派生的删除方法。首先,我们将在Fruit表中插入几条记录,在test-fruit-data.sql中定义数据:。
insert into fruit(id,name,color) values (1,'apple','red');
insert into fruit(id,name,color) values (2,'custard apple','green');
insert into fruit(id,name,color) values (3,'mango','yellow');
insert into fruit(id,name,color) values (4,'guava','green');
Then, we’ll delete all “green” fruit:
然后,我们将删除所有 “绿色 “水果。
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenDeletedByColor_ThenDeletedFruitsShouldReturn() {
List<Fruit> fruits = fruitRepository.deleteByColor("green");
assertEquals("number of fruits are not matching", 2, fruits.size());
fruits.forEach(fruit -> assertEquals("It's not a green fruit", "green", fruit.getColor()));
}
Also, note that we need to use the @Transactional annotation for delete methods.
另外,注意我们需要为删除方法使用@Transactional注解。。
Next, let’s add a similar test case for the second deleteBy method:
接下来,让我们为第二个deleteBy方法添加一个类似的测试案例。
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenDeletedByName_ThenDeletedFruitCountShouldReturn() {
Long deletedFruitCount = fruitRepository.deleteByName("apple");
assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue());
}
3. Derived removeBy Methods
3.派生的removeBy方法
We can also use the removeBy verb to derive delete methods:
我们还可以使用removeBy动词来导出删除方法:。
Long removeByName(String name);
List<Fruit> removeByColor(String color);
Note that there’s no difference in the behavior of the two types of methods.
注意,这两类方法的行为没有任何区别。。
The final interface will look like:
最终的界面将看起来像。
@Repository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
Long deleteByName(String name);
List<Fruit> deleteByColor(String color);
Long removeByName(String name);
List<Fruit> removeByColor(String color);
}
Let’s add similar unit tests for the removeBy methods:
让我们为removeBy方法添加类似的单元测试。
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenRemovedByColor_ThenDeletedFruitsShouldReturn() {
List<Fruit> fruits = fruitRepository.removeByColor("green");
assertEquals("number of fruits are not matching", 2, fruits.size());
}
@Transactional
@Test
@Sql(scripts = { "/test-fruit-data.sql" })
public void givenFruits_WhenRemovedByName_ThenDeletedFruitCountShouldReturn() {
Long deletedFruitCount = fruitRepository.removeByName("apple");
assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue());
}
4. Derived Deleted Methods vs @Query
4.派生的删除方法与@Query的比较
We may come across a scenario that makes the derived method’s name too big or that involves a SQL JOIN between unrelated entities.
我们可能会遇到这样的情况,使得派生方法的名字太大,或者涉及到不相关实体之间的SQL JOIN。
In this case, we can also use the @Query and @Modifying annotations to implement delete operations.
在这种情况下,我们也可以使用@Query和@Modifying注释来实现删除操作。
Let’s see the equivalent code for our derived delete methods, using a custom query:
让我们看看我们的派生删除方法的等效代码,使用一个自定义查询。
@Modifying
@Query("delete from Fruit f where f.name=:name or f.color=:color")
List<int> deleteFruits(@Param("name") String name, @Param("color") String color);
Although the two solutions seem similar, and they do achieve the same result, they take a slightly different approach. The @Query method creates a single JPQL query against the database. By comparison, the deleteBy methods execute a read query, then delete each of the items one by one.
虽然这两种解决方案看起来很相似,而且它们确实达到了相同的结果,但它们采取的方法略有不同。@Query方法针对数据库创建一个单一的JPQL查询。相比之下,deleteBy方法执行一个读取查询,然后一个一个地删除每个项目。
Also, the deleteBy method can return the list of deleted records, while the custom query will return the number of deleted records.
另外,deleteBy方法可以返回已删除记录的列表,而自定义查询将返回已删除记录的数量。
5. Conclusion
5.总结
In this article, we focused on derived Spring Data derived delete methods. The complete source code used in this article can be found over on GitHub.
在这篇文章中,我们重点讨论了Spring Data派生的删除方法。本文中使用的完整源代码可以在GitHub上找到over。