Eclipselink相关对象的历史记录

时间:2014-07-30 08:39:48

标签: jpa eclipselink

我可以使用HistoryCustomizer

创建实体的历史记录
@Entity
@Customizer(MyHistoryCustomizer.class)
public class Employee {..}

HistoryCustomizer就像这样:

public class MyHistoryCustomizer implements DescriptorCustomizer {
    public void customize(ClassDescriptor descriptor) {
        HistoryPolicy policy = new HistoryPolicy();
        policy.addHistoryTableName("EMPLOYEE_HIST");
        policy.addStartFieldName("START_DATE");
        policy.addEndFieldName("END_DATE");
        descriptor.setHistoryPolicy(policy);
    }
}

可以使用“AS_OF”提示

获取历史记录对象
javax.persistence.Query historyQuery = em
                    .createQuery("SELECT e FROM Employee e", Employee.class)
                    .setParameter("id", id)
                    .setHint(QueryHints.AS_OF, "yyyy/MM/dd HH:mm:ss.SSS")
                    .setHint(QueryHints.READ_ONLY, HintValues.TRUE)
                    .setHint(QueryHints.MAINTAIN_CACHE, HintValues.FALSE);

很好但是,如果你开始访问这个历史对象引用的对象,引用的对象将是它们的实际版本。因此,去年的员工(由历史查询提取)将分配当前的地址,而不是去年曾用过的地址。

如何告诉EclipseLink(2.5.0)从过去获取相关对象?

1 个答案:

答案 0 :(得分:5)

为了查询几个实体的历史状态 - 不仅仅是上面的实体 - 我们必须创建一个 EclipseLink特定的HistoricalSession 。通过此会话运行的查询将使用相同的历史时间戳,并表示对象图的正确历史状态。

我在代码的其他部分使用JPA,所以我将开始将JPA Query转换为EclipseLink ReadAllQuery。

HistoricalSession有自己的实体缓存,因此历史实体不会与正常实体混合。

        // Get the EclipseLink ServerSession from the JPA EntitiyManagerFactory
        Server serverSession = JpaHelper.getServerSession(emf);
        // Only a ClientSession can give us a HistoricalSession so ask one from the ServerSession 
        ClientSession session = serverSession.acquireClientSession();
        // Create the HistoricalSessions. A HistoricalSession is sticked to a point in the past and all the queries are executed at that time.
        Session historicalSessionAfterFirstChild = session.acquireHistoricalSession(new AsOfClause(afterFirstChildAdded));

        ReadAllQuery q; 

        Query jpaQuery = em.createQuery(query);
        jpaQuery.setParameter("root", "parent");
        // Extract the EclipseLink ReadAllQuery from the JPA Query. We can use named queries this way.
        q=JpaHelper.getReadAllQuery(jpaQuery);

        // This is a possible EclipseLink bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=441193
        List<Object> arguments = new Vector<Object>();
        arguments.add("parent");
        q.setArgumentValues(arguments);

        Vector<Parent> historyAwareParents ;

        // Execute the query
        historyAwareParents = (Vector<Parent>) historicalSessionAfterFirstChild.executeQuery(q);
        for (Child c : historyAwareParents.get(0).children) {
            System.out.println(c.getExtension() + " " + c.getRoot());
        }