Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » HistoryPolicy OneToOneMapping StackOverflowError(JPA Eclipselink HistoryPolicy OneToOneMapping StackOverflowError)
icon4.gif  HistoryPolicy OneToOneMapping StackOverflowError [message #886221] Thu, 14 June 2012 13:16 Go to next message
Dieter Hubau is currently offline Dieter Hubau
Messages: 2
Registered: June 2012
Junior Member
Hello everyone, long time lurker and first post to Eclipselink forums!

For a project of ours, I have been working on the data layer for quite some time now. The client now would like to historize all data in the model, and be able to retrieve the data given a certain timestamp.

I have added a HistoryCustomizer to all the classes like so:

@Customizer(HistoryDescriptorCustomizer.class)


With my HistoryDescriptorCustomizer looking like this:

@Override
public void customize(ClassDescriptor descriptor) throws Exception {
    HistoryPolicy policy = new HistoryPolicy();
    policy.addHistoryTableName( descriptor.getTableName(),"HIST_" + descriptor.getTableName());
    policy.addStartFieldName("HIST_START_TIME");
    policy.addEndFieldName("HIST_END_TIME");
    descriptor.setHistoryPolicy(policy);
}


So far so good, whenever I create or update a record using JPA (Eclipselink 2.0.2) a history record is added correctly, with the correct timestamps and everything.

Now comes the tricky part, it seems Razz

I'm trying to lookup a Dossier instance for a given date, but when looking for some of its children and OneToOneMappings, JPA throws a StackOverflowError since he seems to be stuck in an infinite loop, querying between two tables with the same two queries over and over...

This is the code used to make the query:

JpaEntityManager em = JpaHelper.getEntityManager(getEntityManager());
AsOfClause asOfClause = new AsOfClause(date);
Session session = em.getServerSession().acquireClientSession();
Session historicalSession = session.acquireHistoricalSession(asOfClause);
try {
    ExpressionBuilder builder = new ExpressionBuilder();
    result = (Dossier) historicalSession.readObject(Dossier.class, builder.get("dossierNumber").equal(dossierNumber));
} finally {
    historicalSession.release();
}


Without showing everything for Dossier, I'll try to show the parts of the datamodel which are relevant to this discussion:

Dossier.java:

@Entity
@Table(name = "DOSSIER")
@Customizer(HistoryDescriptorCustomizer.class)
public class Dossier implements Persistable<Long> {
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false)
    @JoinColumn(name = "CONTACT_ID")
    private Contact contact;
}


Contact.java:

@Entity
@Table(name = "CONTACT")
@Customizer(HistoryDescriptorCustomizer.class)
public class Contact implements Persistable<Long> {
    @OneToOne(mappedBy = "contact", fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name = "ADDRESS_CONTACT_ID")
    @PrivateOwned
    private ContactAddress address;
}


ContactAddress.java:

@Entity
@Table(name = "ADDRESS_CONTACT")
@Customizer(HistoryDescriptorCustomizer.class)
public class ContactAddress extends Address implements Persistable<Long> {
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "CONTACT_ID")
    private Contact contact;
}


Address.java:

@MappedSuperclass
public abstract class Address implements Persistable<Long> {
    @ManyToOne(fetch = FetchType.EAGER, optional = false)
    @JoinColumn(name = "TYPE_ID", nullable = false)
    @JoinFetch
    private ParameterValue type;
}


ParameterValue.java:

@Entity
@Table(name = "PARAMETER_VALUE")
public class ParameterValue implements Persistable<Long> {
    // not important
}


Now, the queries that he keeps on looping on are the following:

Query number 1:

SELECT CONTACT_ID, LAST_NAME, FIRST_NAME, COMPANY_NAME, INSS, CONTACT_FUNCTION FROM HIST_CONTACT WHERE ((CONTACT_ID = ?) AND ((HIST_START_TIME <= ?) AND ((HIST_END_TIME IS NULL) OR (HIST_END_TIME > ?))))


Query number 2:

SELECT t1.ADDRESS_CONTACT_ID, t1.REGION, t1.POSTAL_CODE, t1.STREET, t1.COUNTRY_CODE, t1.MUNICIPALITY, t1.STREET_NUMBER, t1.BOX, t1.MUNICIPALITY_CODE, t1.CONTACT_ID, t1.TYPE_ID, t0.PARAMETER_VALUE_ID, t0.VALUE_EN, t0.START_DATE, t0.STATUS, t0.END_DATE, t0.CODE, t0.VALUE_DE, t0.CREATION_DATE, t0.MODIFICATION_DATE, t0.VALUE_NL, t0.VALUE_FR, t0.PARAMETER_ID, t0.MODIFIED_BY FROM PARAMETER_VALUE t0, HIST_ADDRESS_CONTACT t1 WHERE ((t1.CONTACT_ID = ?) AND (((t1.HIST_START_TIME <= ?) AND ((t1.HIST_END_TIME IS NULL) OR (t1.HIST_END_TIME > ?))) AND (t0.PARAMETER_VALUE_ID (+) = t1.TYPE_ID)))


There you go... What a long-ass post, huh Embarrassed
We've been looking at all kinds of potential problems with this, but there is so little information to be found about EclipseLink history... Kinda hard to find something on a subject this complex. Anyway, if anybody could help, I'll be right here to answer any more questions you might have in order to fix this Smile

Kind regards,
Dieter
Re: HistoryPolicy OneToOneMapping StackOverflowError [message #889746 is a reply to message #886221] Tue, 19 June 2012 14:31 Go to previous message
James Sutherland is currently offline James Sutherland
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

Please include the stack trace.

There are a few odd things,
- try removing the @JoinFetch annotation, this may be related, also the SQL is using an outerjoin, did you set LEFT on your @JoinFetch, also the syntax is odd, it should be printing the outer join in the FROM clause.
- your relationships are LAZY, so odd it could get into a loop, are you somehow triggering the relationships?


James : Wiki : Book : Blog : Twitter
Previous Topic:FUNC make postgre throwing exception
Next Topic:fixed timestamp for start/end values for historical data
Goto Forum:
  


Current Time: Sat Sep 20 18:10:24 GMT 2014

Powered by FUDForum. Page generated in 0.01624 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software