Hello
I use JPA to save some Java classes, as shown below. Saving Y seems to work fine until the database contains elements of class X that have the same identifier as Yxid. I am confused by this. It seems that the JPA implementation I'm using (EclipseLink) does not seem to figure out that although Y is new, Yx is not new, that is, Y must be preserved, but the X relation element must be updated. Any help in figuring out what causes this would be greatly appreciated. I have cited the corresponding fragments of the program source code below, if something is unclear, please feel free to ask me for clarification.
Thanks in advance.
public static interface YY { Object id(); } @Entity @Access(AccessType.FIELD) @Table(name = "X") public class X implements YY { @Id long id; protected X() { this.id = Test.orderId++; } @Override public Long id() { return id; } } public class YPK { private final Date date; private final Long x; public YPK(X x, Date date) { this.date = date; this.x = x.id(); } @Override public boolean equals(Object arg0) { if (arg0 == this) { return true; } else if (arg0 instanceof YPK) { return date.equals(((YPK) arg0).date) && x.equals(((YPK) arg0).x); } return false; } @Override public int hashCode() { return date.hashCode() ^ x.hashCode(); } } @Entity @Access(AccessType.FIELD) @Table(name = "Y") @IdClass(YPK.class) public class Y implements YY { @Id @Temporal(TemporalType.TIMESTAMP) Date date; @Id @ManyToOne(cascade = CascadeType.ALL) private X x; public Y(X x) { this.x = x; date = new DateTime().toDate(); } protected Y() { } @Override public YPK id() { return new YPK(x, date); } } public class Test { public static long orderId = 0; public static long customerId = 0; public static void main(String[] args) { Map<String, String> properties = new HashMap<String, String>(){ { put("javax.persistence.jdbc.url", "jdbc:derby://localhost:1527/myDB;create=false;"); put("javax.persistence.jdbc.driver", "org.apache.derby.jdbc.ClientDriver"); put("javax.persistence.jdbc.user", "myDbUser"); put("javax.persistence.jdbc.password", "passwd");
}
I run the program once when the "drop-and-create-tables" is uncommented, and everything is fine, because there are no X records in the database. I comment on drop-and-create-tables and run it again, but this time I get the following error. Thanks
[EL Warning]: 2011-03-24 06:52:56.047--UnitOfWork(20391510)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL110324065226450' defined on 'X'. Error Code: -1 Call: INSERT INTO X (ID) VALUES (?) bind => [1 parameter bound] Query: InsertObjectQuery( com.test.X@1b6101e ) Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL110324065226450' defined on 'X'. Error Code: -1 Call: INSERT INTO X (ID) VALUES (?) bind => [1 parameter bound] Query: InsertObjectQuery( com.test.X@1b6101e ) at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102) at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63) at com.test.Test.saveItems(Test.java:80) at com.test.Test.main(Test.java:56)
The logs are here: 1st launch successful Second launch error
user63904
source share