Envers - @ManyToOne映射实体中的字段修改,不会触发AuditedJoinColumn中的更新

时间:2014-10-11 15:45:19

标签: hibernate jpa hibernate-envers

考虑这些课程:

@Audited
@Entity
public class Child
{
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
    @JoinColumn(nullable = false)
    private Father father;

    private String name;
}


@Audited
@Entity
public class Father
{
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
    private Set<Child> children;

    public void addChild(Child child)
    {
        if (null == this.children)
            this.children = new HashSet<>();

        this.children.add(child);
    }

    private String name;
}

创建子项和父项时,映射正确完成。建立关系后,不会在AuditedJoinColumn中更新子项名称。

因此在此测试之后:

import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.envers.query.AuditEntity;
import org.hibernate.envers.query.AuditQuery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.Date;
import java.util.List;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;

public class BasicTest
{
    private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("EnversTest");

    private Long fatherId;
    private Long childId;

    @Before
    public void setup()
    {
        EntityManager em = emf.createEntityManager();

        try
        {
            em.getTransaction().begin();

            Father father = new Father();
            father.setName("Dad");

            Child child = new Child();
            child.setName("Sam");
            child.setFather(father);

            father.addChild(child);

            em.persist(child);
            em.persist(father);
            em.getTransaction().commit();

            this.fatherId = father.getId();
            this.childId = child.getId();

            /////// Change child's name ///////

            em.getTransaction().begin();
            child.setName("John");
            em.persist(child);
            em.getTransaction().commit();
        }
        finally
        {
            em.close();
        }
    }

    @Test
    public void validateChildForAllRevisions()
    {
        EntityManager em = emf.createEntityManager();

        try
        {
            { // assert there are 2 revision of child
                List<Object[]> changes = getAllRevisions(Child.class, childId, em);
                assertNotNull(changes);
                assertEquals(2, changes.size());
                assertEquals("Sam", ((Child)changes.get(0)[0]).getName());
                assertEquals("John", ((Child)changes.get(1)[0]).getName());
            }

            { // assert there is 1 revision of father
                List<Object[]> changes = getAllRevisions(Father.class, fatherId, em);
                assertNotNull(changes);
                assertEquals(1, changes.size());

                // make sure latest father has a child named John
                Father lastRevOfFather = (Father)changes.get(0)[0];
                assertNotNull(lastRevOfFather);
                assertNotNull(lastRevOfFather.getChildren());
                assertEquals(1, lastRevOfFather.getChildren().size());

                for (Child auditedChild : lastRevOfFather.getChildren())
                    assertEquals("John", auditedChild.getName());
            }
        }
        finally
        {
            em.close();
        }
    }

    @Test
    public void validateChildNameAtSpecificRevision()
    {
        EntityManager em = emf.createEntityManager();

        try
        {
            Date time = new Date();

            List<Object[]> changes = getLastRevision(Father.class, fatherId, em, time);
            assertNotNull(changes);
            assertEquals(1, changes.size());

            Father auditedFather = (Father)changes.get(0)[0];
            assertNotNull(auditedFather);
            assertNotNull(auditedFather.getChildren());
            assertEquals(1, auditedFather.getChildren().size());

            for (Child auditedChild : auditedFather.getChildren())
                assertEquals("John", auditedChild.getName());
        }
        finally
        {
            em.close();
        }
    }

    public List<Object[]> getAllRevisions(final Class clazz, final Long entityId, EntityManager em)
    {
        AuditReader reader = AuditReaderFactory.get(em);

        AuditQuery query = reader.createQuery().forRevisionsOfEntity(clazz, false, false);
        query.add(AuditEntity.id().eq(entityId));

        return query.getResultList();
    }

    public List<Object[]> getLastRevision(final Class clazz, final Long entityId, EntityManager em, final Date time)
    {
        AuditReader reader = AuditReaderFactory.get(em);
        Number rev = reader.getRevisionNumberForDate(time);

        AuditQuery query = reader.createQuery().forRevisionsOfEntity(clazz, false, false);

        query.add(AuditEntity.id().eq(entityId));
        query.add(AuditEntity.revisionNumber()
                             .maximize()
                             .add(AuditEntity.revisionNumber().le(rev))
                             .computeAggregationInInstanceContext());

        return query.getResultList();
    }

    @After
    public void cleanup()
    {
        EntityManager em = emf.createEntityManager();

        try
        {
            em.getTransaction().begin();
            em.remove(em.find(Father.class, fatherId));
            em.getTransaction().commit();
        }
        finally
        {
            em.close();
        }
    }
}

子名称比较断言失败: org.junit.ComparisonFailure:expected:&lt; [John]&gt;但是:&lt; [Sam]&gt;

到目前为止,我认为强制重新映射的唯一方法是改变父亲的某些东西。

我希望有更好的方法来做到这一点。

0 个答案:

没有答案