【问题标题】:Why does DataJpaTest fail when saving OneToMany-related data in this pattern?以这种模式保存 OneToMany 相关数据时,为什么 DataJpaTest 会失败?
【发布时间】:2022-10-05 01:44:47
【问题描述】:

我在下面有三个 Hibernate @Entity,它们模仿了我的生产应用程序中的失败:

@Entity
@Data
@SuperBuilder(toBuilder = true)
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dog extends Animal {
    String barkType;
}

Dog 实体对此类 Animal 使用 JOINED 继承:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Data
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Animal {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Type(type = "uuid-char")
    private UUID id;

    @OneToMany(cascade = CascadeType.REMOVE)
    @JoinColumn(name = "animalId", referencedColumnName = "id", insertable = false, updatable = false)
    @Builder.Default
    private List<Toy> toys = new ArrayList<>();
}

这个Toy实体与父类相关,Animal

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Toy {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Type(type = "uuid-char")
    private UUID id;
    
    @Type(type = "uuid-char")
    private UUID animalId;
    
    private String shape;
}

这是我正在测试的实现:

@Service
@AllArgsConstructor
public class DogService {

    DogRepository repository;
    ToyRepository toyRepository;

    @Transactional
    public Dog saveDogDTO(DogDTO dogDTO) {
        Dog entity = Dog.builder()
                .barkType(dogDTO.getBarkType())
                .build();

        repository.save(entity);
        toyRepository.save(Toy.builder()
                .shape(dogDTO.getToyShape())
                .animalId(entity.getId())
                .build());

        return entity;
    }
}

这是我失败的测试,在最后一行失败:

@DataJpaTest
class DogServiceTests {

    private DogService dogService;

    @Autowired
    private DogRepository dogRepository;

    @Autowired
    private ToyRepository toyRepository;

    @Test
    void save_not_working_example() {
        dogService = new DogService(dogRepository, toyRepository);

        var dogDTO = DogDTO.builder()
                .barkType("big bark")
                .toyShape("some shape")
                .build();

        var savedDog = dogService.saveDogDTO(dogDTO);

        assertThat(dogRepository.count()).isEqualTo(1);
        assertThat(toyRepository.count()).isEqualTo(1);

        var findByIdResult = dogRepository.findById(savedDog.getId());
        assertThat(findByIdResult.get().getToys()).hasSize(1);
    }

}

测试失败消息:

Expected size: 1 but was: 0 in:
[]
java.lang.AssertionError: 
Expected size: 1 but was: 0 in:
[]

问题似乎是双 JPA 存储库在 @Transaction 中保存冲突。有没有办法克服这个问题?我尝试将@Transactional(propagation = Propagation.NEVER) 添加到测试中,但后来我得到了这个失败:

failed to lazily initialize a collection of role: com.example.datajpatest.demo.models.Animal.toys, could not initialize proxy - no Session
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.datajpatest.demo.models.Animal.toys, could not initialize proxy - no Session

【问题讨论】:

  • dog Repository.count() 和 toy Repository.count() 实际上在做什么?

标签: spring-boot hibernate spring-data-jpa data-jpa-test


【解决方案1】:

请在此处尝试此映射:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Data
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Animal {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Type(type = "uuid-char")
    private UUID id;

    @OneToMany(mappedBy = "animal", cascade = CascadeType.REMOVE)
    @Builder.Default
    private List<Toy> toys = new ArrayList<>();
}

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Toy {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Type(type = "uuid-char")
    private UUID id;
    
    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "animalId")
    private Animal animal;
    
    private String shape;
}

【讨论】:

    猜你喜欢
    • 2020-05-05
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    • 2015-06-09
    • 1970-01-01
    相关资源
    最近更新 更多