通过@RepositoryEventHandler使用事件实现Spring Data REST中的前后操作,Spring Data REST可以帮助开发人员在将Repository类转换为REST端点时,只需很少代码就能创建REST应用程序。在此示例中,我们将探讨如何在使用@RepositoryEventHandler及其相关注释持久化实体之前和之后执行操作。
实体和存储库类
有两个@Entity: Author 和 Book,以及相应的JpaRepository 类: AuthorRepository 和BookRepository
Author:
@Entity @Data @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Author {
@Id @GeneratedValue private Long id;
@NotBlank private String name;
@OneToMany(mappedBy = "author", cascade = CascadeType.REMOVE) private Set<Book> books;
private Status status;
public enum Status {
ACTIVE,
INACTIVE
} }
|
其JpaRepository如下:
public interface AuthorRepository extends JpaRepository<Author, Long> { }
|
Book:
@Entity @Data @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Book {
@Id @GeneratedValue private Long id;
@JoinColumn @ManyToOne(optional = false) @NotNull private Author author;
@NotBlank private String title;
}
|
其仓储:
public interface BookRepository extends JpaRepository<Book, Long> { }
|
我们可以看到,这两个类都是普通的JPA实体类,没有任何其他配置。一旦我们启动应用程序,就会有两个REST端点可用; /authors和/books。添加作者验证
我们将确保一个Author的Book必须是ACTIVE添加到数据库之前。为此,我们将使用带@HandleBeforeCreate的@RepositoryEventHandler。
通过使用RepositoryEventHandler注释我们的类,我们通知Spring该类将管理与存储库相关的事件。除此之外,我们将使用HandleBeforeCreate,它指示在持久给定之前需要执行该方法@Entity。
我们将在AuthorRepositoryEventHandler中实现我们的验证:
@RepositoryEventHandler @AllArgsConstructor @SuppressWarnings("unused") public class AuthorRepositoryEventHandler {
@HandleBeforeCreate public void validateAuthorStatus(Book book) { Author author = book.getAuthor();
Assert.isTrue(Author.Status.ACTIVE == author.getStatus(), "book author must be active"); }
}
|
我们可以看到,方法validateAuthorStatus将Book作为入参并验证Author的status,确保Author是ACTIVE。
配置类
接下来是通知应用程序我们想要注册AuthorRepositoryEventHandler为a Bean,因此将在使用相关实体时触发。这可以在RepositoryHandlerConfiguration中找到:
@Configuration public class RepositoryHandlerConfiguration { @Bean public AuthorRepositoryEventHandler authorRepositoryEventHandler(){ return new AuthorRepositoryEventHandler(); } }
|
验证实施
与往常一样,我们将通过集成测试验证我们的实现。在下面的测试中,我们将创建一个Author 带状态INACTIVE,然后创建一个Book关联到这个Author关联。
我们期望返回Internal Server Error:book author must be active:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class BookRepositoryRestTests {
@Autowired private MockMvc mvc;
@Test public void createBookWithInactiveAuthor() throws Exception { String authorUri = getAuthorUri(INACTIVE);
JSONObject request = new JSONObject();
request.put("author", authorUri); request.put("title", "If");
mvc.perform( post("/books") .content(request.toString()) ) .andExpect(status().isInternalServerError()) .andExpect(jsonPath("$.message", is("book author must be active"))); }
private String getAuthorUri(Author.Status status) throws Exception { JSONObject request = new JSONObject();
request.put("name", "Rudyard Kipling"); request.put("status", status.name());
return mvc.perform( post("/authors") .content(request.toString()) ) .andExpect(status().isCreated()) .andReturn().getResponse().getHeader(LOCATION); }
}
|
通过正确的实现,上面的测试应该通过。