测试 JpaRepository findById 为 UUID 返回 null

问题描述

这里是春季新手,
我想测试存储库的 findById() 方法,但它无法找到该条目,即使它已保存(并存在)在数据库中:

@DataJpaTest
class CustomerRepoIntegration {

    @Autowired
    CustomerRepo customerRepo;

    @Test
    @Transactional
    void findById() {
        UUID uuid = UUID.randomUUID();
        Customer customer = new Customer(uuid);
        customerRepo.save(customer);

        List<Customer> allCustomers = customerRepo.findAll();
        assertEquals(1,allCustomers.size());

        Optional<Customer> foundCustomer = customerRepo.findById(uuid);
        assertTrue(foundCustomer.isPresent());
    }
}

虽然第一个断言成功,但第二个断言失败:

Error:  Failures: 
Error:    CustomerRepoIntegration.findById:32 expected: <true> but was: <false>

其余代码

// CustomerRepo.java
public interface CustomerRepo extends JpaRepository<Customer,UUID> {}
// Customer.java
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Customer implements Serializable {
    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(
            name = "UUID",strategy = "org.hibernate.id.UUIDGenerator"
    )
    private UUID id;
}

我还在这里制作了一个复制仓库:https://github.com/ofhouse/stackoverflow-65818312

解决方法

尝试使用

customerRepo.saveAndFlush(customer) 代替 save(customer)

此外,如果您配置了负责自动生成 id 的实体注释,更好的想法是不要干扰这种机制来创建您自己的 UUID 并初始化实体。 Hibernate 会自动为您完成。

为什么不呢?

Hibernate 有自己的机制,取决于带有 @Id 注释的标记字段是否将实体与 EntityManager 合并或持久化(如果该字段为 null 或包含数据)。

代替

UUID uuid = UUID.randomUUID();
Customer customer = new Customer(uuid);

你可以简单地做

Customer customer = new Customer();

并从实体的持久化实例中获取 UUID:

var persistedCustomer = customerRepo.saveAndFlush(customer);
...
Optional<Customer> foundCustomer = customerRepo.findById(persistedCustomer.uuid);