| Summary: | HistoryPolicy Problem with PK GenerationType.IDENTITY on PostgreSQL | ||||||
|---|---|---|---|---|---|---|---|
| Product: | z_Archived | Reporter: | Ecmel Ercan <ecmel.ercan> | ||||
| Component: | Eclipselink | Assignee: | Nobody - feel free to take it <nobody> | ||||
| Status: | NEW --- | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P2 | CC: | acc-clps, nicholas, nicolas.marcotte, nrutherford, renso, sam.ratcliff, tom.ware | ||||
| Version: | unspecified | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | PC | ||||||
| OS: | Windows XP | ||||||
| Whiteboard: | postgresql | ||||||
| Attachments: |
|
||||||
|
Description
Ecmel Ercan
Please post information about how you entity is defined and mapped. (java, annotations, orm.xml, deployment xml) @MappedSuperclass
@Customizer(EntityCustomizer.class)
public abstract class Persistent implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
private Integer version;
protected Persistent() {
super();
}
public Long getId() {
return id;
}
public Integer getVersion() {
return version;
}
}
@Entity
public class Account extends Persistent {
private static final long serialVersionUID = 1L;
...
}
In EntityCustomizer I set the HistoryPolicy. This works with SEQUENCE but not with IDENTITY.
Tested only on PostgreSQL.
Setting target and priority. See the following page for the meanings of these fields: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines Community: Please vote for this bug if it is important to you. Votes are one of the main criteria we use to determine which bugs to fix next. This also is a problem with MS SQL Server This is also a problem with MySQL but using SEQUENCE or TABLE strategies do not work. here is a crude hack to fix this problem:
HistoryPolicy historyPolicy = new HistoryPolicy(){
@Override
public void logicalInsert(ObjectLevelModifyQuery writeQuery, boolean isUpdate) {
Sequence oldValue = writeQuery.getDescriptor().getSequence();
writeQuery.getDescriptor().setSequence(new Sequence(){
@Override
public boolean shouldAcquireValueAfterInsert() {
return false;
}
@Override
public boolean shouldUseTransaction() {
return false;
}
@Override
public Object getGeneratedValue(Accessor accessor, AbstractSession writeSession, String seqName) {
return new Object();
}
@Override
public Vector getGeneratedVector(Accessor accessor, AbstractSession writeSession, String seqName, int size) {
return new Vector();
}
@Override
public void onConnect() {
}
@Override
public void onDisconnect() {
}
});
super.logicalInsert(writeQuery, isUpdate);
writeQuery.getDescriptor().setSequence(oldValue);
}
};
Created attachment 251408 [details]
A better correction of this bug
The quick and dirty hack I posted friday was not thread safe. It can lead to data corruption under load. Here is a cleaner, thread safe, fix.
The simplest way I found to fix this bug was, to clone the descriptor in the initialise method and to replace the sequance, with a DummySequance that does nothing.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |