为什么Hibernate OneToMany映射必须显式刷新实体才能在单元测试中工作



在OneToMany映射上进行测试时,我花了几个小时才弄清楚这种令人惊讶的行为。我重读了实体d hibernate指南,仔细检查代码,测试desisgn,最终找出可能与hibernate缓存设计有关的根本原因。以下是代码摘录:

@Entity
public class Organization {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;
@ManyToOne
@JoinColumn(name="cooperation_id")
private Cooperation cooperation;
@ManyToOne(optional=true)
@JoinColumn(name="organization_id", nullable=true)
private Organization upperLevel;
@OneToMany(mappedBy="upperLevel")
private Collection<Organization> subOrganizations = new ArrayList<Organization>();
@OneToOne(mappedBy="organization")
private TimeoffSetting timeoffSetting;
private String name;
...

JUNIT测试:

@PersistenceContext
private EntityManager entityManager
@Transactional
public void organization() {
    Organization organization_it = new Organization(cooperation, "IT");
    organization_it.setUpperLevel(organizationTop);
    organization_it = organizationRepository.save(organization_it);
    Organization organization_hr = new Organization(cooperation, "HR");
    organization_hr.setUpperLevel(organizationTop);
    organization_hr = organizationRepository.save(organization_hr);
    Organization organization_unix = new Organization(cooperation, "UNIX");
    organization_unix.setUpperLevel(organization_it);
    organization_unix = organizationRepository.save(organization_unix);
    boolean hasIt = false;
    boolean hasHr = false;
    Iterable<Organization> organizations = organizationRepository.findAll();
    for(Organization o: organizations) {
        entityManager.refresh(o);
        if (o.getName() == "cooperation") {
            org.junit.Assert.assertTrue(o.isTopLevel());
            org.junit.Assert.assertEquals(o.getSubOrganizations().size(), 2);
        }
    ...

请注意这里的entityManager.refresh(o)方法调用,如果我不刷新实体,assertEquals(getSubOrganizations().size(),2)OneToMany映射测试将导致失败。通过谷歌搜索互联网,Spring的集成测试在编写ORM测试时应该更加谨慎。一篇文章可能是有用的春季陷阱交易测试

很简单:您分配了It和HR的upperLevel组织,但忽略了通过将It和HR添加到顶级的subOrganizations列表来保持对象图的一致性。

这对Hibernate来说并不是一个真正的问题,因为您负责设置每个双向关联的所有者侧,这就是Hibernate保持这种关联所需要的全部内容。

但是,由于对象不是由Hibernate创建和填充的,而是由您创建和填充,因此它们就是您创建的。正如您在使用refresh()时注意到的,当Hibernate负责创建和填充实体时,关联的双方是一致的。

最新更新