Spring Boot 2.x实战68 - Spring Data 12 - Spring Data JPA领域事件(Domain Events)

本文介绍了在Spring Boot 2.x中如何利用Spring Data JPA实现领域事件,遵循领域驱动设计(DDD)的小聚合原则。通过领域事件,避免了聚合之间的直接关联,减少了事务边界,提升性能。文中详细展示了如何定义和处理领域事件,以及在实际操作中如何发布和监听这些事件,特别是在雇员和聚合根之间的交互。同时,文章还提及作者的新书,涵盖了Spring Boot的广泛知识,包括Spring Web MVC、响应式编程和微服务等。
2.8 领域事件

由于在DDD中采用了“设计小聚合”的原则,因此避免了领域模型的相互关联,从而避免了在应用演进中形成“大泥球”(Big Ball of Mud),也因为上述的原因,本书将不讲解@OneToMany、@ManyToMany等关联注解。聚合之间在没有了关联关系后,聚合之间的数据通讯通过领域事件来完成,领域事件是由聚合根发出的。

Spring Data对领域事件做了专门的支持,使用@DomainEvents注解注册领域事件或者继承AbstractAggregateRoot使用它的registerEvent方法注册事件。

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Person {
   
   
    @DomainEvents // 使用集合类注册事件列表
    Collection<Object> domainEvents(){
   
   
        List<Object> events= new ArrayList<Object>();
        events.add(new PersonSaved(this.id, this.name, this.age));
        return events;
    }

    @AfterDomainEventPublication //所有事件发布完成后调用,一般用来清空事件列表
    void callbackMethod() {
   
   
       domainEvents().clear(); 
    }
}

当Repository每一次调用save方法时,领域事件都会被发布。

我们的领域事件定义:

import lombok.Value;
@Value
public class PersonSaved {
   
   
    
<think>好的,我需要帮助用户展示一个Spring Boot的测试类,其中包含使用分页查询Discuss实体的方法。用户要求一个JUnit测试的例子,涉及分页、Discuss实体和Repository。 首先,我得回忆一下Spring Boot中如何进行分页查询。通常,我们会使用Spring Data JPA的Pageable接口来实现分页。Repository层需要定义返回Page<T>的方法,比如通过方法名派生查询或者使用@Query注解。 接下来,测试类需要用到JUnit 5,所以应该使用@SpringBootTest来启动整个应用上下文,注入Repository。然后,在测试方法中,模拟分页参数,比如页码和每页大小,创建PageRequest对象。调用Repository的分页方法,获取结果后,进行断言验证。 还要考虑测试数据的准备。可以使用@DataJpaTest来只加载JPA相关的配置,但用户可能希望一个完整的集成测试,所以用@SpringBootTest更合适。另外,可能需要用@TestConfiguration或者手动插入测试数据到数据库。 需要确保Discuss实体有正确的JPA注解,比如@Entity、@Id等。Repository接口应该继承JpaRepository<Discuss, Long>,并且可能有类似findAll(Pageable pageable)的方法。 现在,整合这些元素,编写测试类。可能需要模拟分页参数,调用方法,检查返回的Page对象中的内容、页码、每页数量等是否符合预期。 最后,要确保代码示例正确,语法无误,并解释关键步骤。可能还需要引用用户提供的参考资料,比如提到Spring Boot和MyBatis的使用,但具体引用可能需要调整。</think>以下是使用Spring BootSpring Data JPA实现分页查询的测试类示例,包含Discuss实体和Repository的完整演示: ### 1. 实体类定义 ```java @Entity @Table(name = "discuss") public class Discuss { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String content; // getters/setters省略 } ``` ### 2. Repository接口 ```java @Repository public interface DiscussRepository extends JpaRepository<Discuss, Long> { // 继承自带的分页查询方法 Page<Discuss> findAll(Pageable pageable); // 自定义分页查询示例 @Query("SELECT d FROM Discuss d WHERE d.content LIKE %:keyword%") Page<Discuss> searchByKeyword(@Param("keyword") String keyword, Pageable pageable); } ``` ### 3. 测试类示例 ```java @SpringBootTest @Transactional @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class DiscussRepositoryTest { @Autowired private DiscussRepository discussRepository; @BeforeEach void setUp() { // 初始化测试数据 IntStream.rangeClosed(1, 15).forEach(i -> { Discuss discuss = new Discuss(); discuss.setContent("Test content " + i); discussRepository.save(discuss); }); } @Test void testFindAllWithPagination() { // 创建分页请求(第2页,每页5条) PageRequest pageRequest = PageRequest.of(1, 5, Sort.by("id").ascending()); Page<Discuss> resultPage = discussRepository.findAll(pageRequest); // 验证分页结果 assertThat(resultPage.getNumber()).isEqualTo(1); // 当前页码 assertThat(resultPage.getSize()).isEqualTo(5); // 每页数量 assertThat(resultPage.getTotalElements()).isEqualTo(15); // 总记录数 assertThat(resultPage.getTotalPages()).isEqualTo(3); // 总页数 assertThat(resultPage.getContent()).hasSize(5); // 当前页记录数 } @Test void testCustomSearchWithPagination() { // 添加特殊测试数据 Discuss specialPost = new Discuss(); specialPost.setContent("Special keyword post"); discussRepository.save(specialPost); PageRequest pageRequest = PageRequest.of(0, 3); Page<Discuss> result = discussRepository.searchByKeyword("keyword", pageRequest); assertThat(result.getContent()) .hasSize(1) .extracting(Discuss::getContent) .containsExactly("Special keyword post"); } } ``` ### 关键点说明: 1. **分页参数构建**:使用`PageRequest.of(page, size)`创建分页请求,支持排序参数 2. **分页结果处理**:返回的`Page<T>`对象包含内容、分页元数据等信息 3. **测试数据准备**:使用`@BeforeEach`初始化测试数据,保证测试独立性 4. **事务管理**:`@Transactional`确保测试结束后自动回滚数据变更 5. **数据库配置**:`@AutoConfigureTestDatabase`保持使用真实数据库配置[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值