HistoryPolicy reuse class descriptor causing error on Postgres with GenerationType.IDENTITY [message #1719079] |
Tue, 05 January 2016 00:57 |
Clovis Wichoski Messages: 11 Registered: January 2016 |
Junior Member |
|
|
Hi,
I'm using DescriptorCustomizer to configure a HistoryPolicy for some classes as follow:
public void customize(ClassDescriptor cd) throws Exception {
HistoryPolicy policy = new HistoryPolicy();
policy.addHistoryTableName(cd.getTableName().concat("_audit"));
policy.addStartFieldName("audit_date_start");
policy.addEndFieldName("audit_date_end");
cd.setHistoryPolicy(policy);
}
The Entity ids are declared as:
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
When we insert an object the history works like expected, but when we update an object, we got the exception:
[javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: lastval is not yet defined in this session
Error Code: 0
Call: select lastval()
Query: ValueReadQuery(name="SEQ_GEN_IDENTITY" sql="select lastval()")] with root cause
org.postgresql.util.PSQLException: ERROR: lastval is not yet defined in this session
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:560)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:302)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1009)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:644)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:560)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2055)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:306)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelect(DatasourceCallQueryMechanism.java:281)
at org.eclipse.persistence.queries.DataReadQuery.executeNonCursor(DataReadQuery.java:197)
at org.eclipse.persistence.queries.DataReadQuery.executeDatabaseQuery(DataReadQuery.java:152)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:904)
at org.eclipse.persistence.queries.DataReadQuery.execute(DataReadQuery.java:137)
at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:3270)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1857)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1839)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1790)
at org.eclipse.persistence.sequencing.QuerySequence.select(QuerySequence.java:309)
at org.eclipse.persistence.sequencing.QuerySequence.updateAndSelectSequence(QuerySequence.java:254)
at org.eclipse.persistence.sequencing.StandardSequence.getGeneratedValue(StandardSequence.java:61)
at org.eclipse.persistence.sequencing.Sequence.getGeneratedValue(Sequence.java:225)
at org.eclipse.persistence.internal.sequencing.SequencingManager$NoPreallocation_State.getNextValue(SequencingManager.java:696)
at org.eclipse.persistence.internal.sequencing.SequencingManager.getNextValue(SequencingManager.java:1107)
at org.eclipse.persistence.internal.sequencing.ClientSessionSequencing.getNextValue(ClientSessionSequencing.java:70)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:362)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.assignSequenceNumber(ObjectBuilder.java:335)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectAndRowWithSequenceNumber(DatabaseQueryMechanism.java:859)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:372)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165)
at org.eclipse.persistence.history.HistoryPolicy.logicalInsert(HistoryPolicy.java:770)
at org.eclipse.persistence.history.HistoryPolicy.postUpdate(HistoryPolicy.java:722)
at org.eclipse.persistence.history.HistoryPolicy.postUpdate(HistoryPolicy.java:714)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1097)
at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:904)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:803)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1857)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1839)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1790)
at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:273)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:131)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4263)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:278)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:134)
Debugging the source code of EclipseLink version 2.6.2, we can see that the problem is on method insertObject declared at line 333 of class org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.
at line 335 the instruction:
boolean usesSequencing = descriptor.usesSequenceNumbers();
This instruction uses the descriptor of original class, and the logic bellow act as the insertion is about the original object, and not for the table HistoryTable defined that dont have serial ID as that must reflect the same ID generated on, with this analyse I think this is a BUG, but before to create a BUG for this, I would discuss here in community, what approach are you doing to maintain the history/audit with EclipseLink? The refactor of this feature is difficult?
TIA
ps: Insert, then update works, to get the exception, you need to start the system and update a previous created object. (I think of this because generated IDs stay in JDBC connection alive that gives some value to lastval SQL function, but can lead to other side effects)
|
|
|
|
Powered by
FUDForum. Page generated in 0.02638 seconds