[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [eclipselink-users] Configuring History Policy for @OneToMany
|
We have solved the problem by setting a ThreadLocal<Timestamp> (unique time
for the running transaction) for the entire transaction of updated entities.
This time is used in combination with the events below to set start- and
end-times correct.
* PreInsertEvent
* PostMergeEvent
* AboutToUpdateEvent
With this solution all entities have the same start- and end-time.
I log a bug as you recommend.
James Sutherland wrote:
>
> Your customizer should be run twice on startup as you have the customizer
> set for two classes, and each class needs to be customized.
>
> The start_time may differ slightly for each insert, as the insert may
> occur at different times (more than one millisecond), this should not
> matter however, the relationship between the rows is based on a range of
> time. It would probably be better to have only a single transaction start
> time used however, please log a bug for this.
>
> If the merge only changed the Builder but not the name, then only the
> build will be inserted into. Both versions of the building will have the
> same name as the date range encompasses both.
>
> If you created a historical session for the point in time that the
> Building was inserted, but before the Name was inserted, then it may not
> have a name if they inserts took more than 1 millisecond, but any point in
> time after the insert of the Name would get both correctly.
>
>
>
> Daniel Rickardsson wrote:
>>
>> Hi All,
>>
>> My problem is about to get the history working for the relation
>> OneToMany.
>>
>> I have set up a simple project with the following entities:
>> * Building
>> * BuildingName
>>
>> Here is my Building:
>> @Entity
>> @Historical
>> @Customizer(AnnotatedCustomizers.class)
>> public class Building extends AbstractEntity {
>> ...
>> ...
>> @PrivateOwned
>> @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,
>> mappedBy = "building")
>> private Collection<BuildingName> names = new
>> ArrayList<BuildingName>();
>> ...
>> ...
>> public void addName(final BuildingName buildingName) {
>> buildingName.setBuilding(this);
>> this.names.add(buildingName);
>> }
>> }
>>
>> Here is my BuildingName:
>> @Entity
>> @Historical
>> @Customizer(AnnotatedCustomizers.class)
>> public class BuildingName extends AbstractEntity {
>> ...
>> ...
>> @ManyToOne
>> @JoinColumn(nullable = false)
>> private Building building;
>> }
>>
>> The AnnotatedCustomizers gets triggered for all annotations in class, and
>> for the @Historical we call:
>>
>> public class HistorySupport implements
>> AnnotatedDescriptorCustomizer<Historical> {
>> ...
>> ...
>>
>> @Override
>> public void customize(final ClassDescriptor descriptor, final
>> Historical annotation) throws Exception {
>> this.customize(descriptor);
>> }
>>
>> @Override
>> public void customize(final ClassDescriptor descriptor) throws
>> Exception {
>> if (descriptor.getTableName().equals("BUILDING")) {
>> HistoryPolicy policy = new HistoryPolicy();
>> policy.addStartFieldName("BUILDING.ROW_START");
>> policy.addEndFieldName("BUILDING.ROW_END");
>>
>> String sourceTableName = descriptor.getTableName();
>> this.logger.debug("descriptor tableName {}",
>> sourceTableName);
>>
>> policy.addHistoryTableName("BUILDING", "BUILDING_HIST");
>>
>> policy.setShouldHandleWrites(true);
>>
>> descriptor.setHistoryPolicy(policy);
>> } else {
>> HistoryPolicy policy = new HistoryPolicy();
>> policy.addStartFieldName("BUILDINGNAME.ROW_START");
>> policy.addEndFieldName("BUILDINGNAME.ROW_END");
>>
>> String sourceTableName = descriptor.getTableName();
>> this.logger.debug("descriptor tableName {}",
>> sourceTableName);
>>
>> policy.addHistoryTableName("BUILDINGNAME",
>> "BUILDINGNAME_HIST");
>>
>> policy.setShouldHandleWrites(true);
>>
>> descriptor.setHistoryPolicy(policy);
>> }
>> }
>> }
>>
>> When persisting the above code is triggered twice... so there will be one
>> HistoryPolicy for each entity?! This does not feel right.
>>
>> When testing:
>> * persist of Building and BuildingName => EclipseLink writes to
>> _HIST-tables but the ROW_START differs.
>> * and then doing a merge of Building gives me another row in _HIST-table
>> for Building but not for BuildingName?
>> * and then when I query with a HistoricalSession (DateTime for ROW_START
>> in Building (HIST) when first inserted) I don't receive BuildingName
>> because ROW_START differs?
>>
>> Here is my HistoricalSession query code:
>> public <T extends AbstractEntity>T queryByHistory(final Class<T> entity,
>> final String uuid, final DateTime time) {
>>
>> ReadObjectQuery query = new ReadObjectQuery(entity);
>>
>> query.setSelectionCriteria(query.getExpressionBuilder().get("objectId").equal(uuid));
>> Session historicalSession =
>> this.entityManager.getServerSession().acquireClientSession().acquireHistoricalSession(
>> new AsOfClause(time.getMillis()));
>> return (T) historicalSession.executeQuery(query);
>> }
>>
>> Can anyone see what's wrong?
>>
>> /Daniel
>>
>
>
--
View this message in context: http://old.nabble.com/Configuring-History-Policy-for-%40OneToMany-tp27874092p28030804.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.