SQL INSERT with @ReturnInsert on @Id with InheritanceType.JOINED doesn't return ID subsequent INSERTs
I have encountered the following problem on both 2.7.11 and the current 4.0.0-RC2 Version.
I used to have the following class:
@Entity
@Table(name="DOCUMENT")
public class Document {
@Id
@ReturnInsert(returnOnly = true)
private long id;
@ManyToMany
@JoinTable(name = "DOCUMENT_LOGIN", joinColumns = @JoinColumn(name = "DOCID"), inverseJoinColumns = @JoinColumn(name = "LOGINID"))
private Set<Login> logins;
}
which was mapped to a table in an Oracle DB where the id column is an identity column, to automatically generate ids.
Persisting a new Document object with a Login object attached worked fine:
Document document = new Document();
document.getLogins().add(login);
EntityManager entityManager = ...;
entityManager.persist(document);
EclipseLink inserted the row into the Document table, fetched the returned id and used that id to insert the relationship between document and login:
[EL Fine]: sql: --BEGIN INSERT INTO DOCUMENT (...) VALUES (...) RETURNING ID INTO ?; END;
bind => [..., => ID]
[EL Finest]: query: --Assign return row DatabaseRecord(
DOCUMENT.ID => 1300)
[EL Finest]: query: --Execute query DataModifyQuery(name="logins" )
[EL Fine]: sql: --INSERT INTO DOCUMENT_LOGIN (LOGINID, DOCID) VALUES (?, ?)
bind => [8, 1300]
Here the new Document id 1300 was returned and used in the login table.
Due to a new requirment I turned the Document class into an abstract class and added new subtypes of document with matching tables.
In the now abstract Document class I added the @Inheritance annotation to use the InheritanceType.JOINED for the subtypes as following
@Entity
@Table(name="DOCUMENT")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Document {
@Id
@ReturnInsert(returnOnly = true)
private long id;
@ManyToMany
@JoinTable(name = "DOCUMENT_LOGIN", joinColumns = @JoinColumn(name = "DOCID"), inverseJoinColumns = @JoinColumn(name = "LOGINID"))
private Set<Login> logins;
}
One example of a subtype is:
@Entity
@Table(name="DOCUMENT_PERSON")
@DiscriminatorValue(value = "1")
public class DocumentPerson extends Document {
@ManyToOne
@JoinColumn(name="PERSONID")
private Person person;
}
The problem i am encountering now is that EL doesn't seem to include the return statement in first INSERT statement anymore, leading to invalid INSERTS into the other tables:
[EL Fine]: sql: --INSERT INTO DOCUMENT (...) VALUES (...)
bind => [...]
[EL Finest]: --Execute query DataModifyQuery(name="logins" )
[EL Fine]: sql: --INSERT INTO DOCUMENT_PERSON (PERSONID, ID) VALUES (?, ?)
bind => [3, 0]
[EL Fine]: sql: --INSERT INTO DOCUMENT_LOGIN (LOGINID, DOCID) VALUES (?, ?)
bind => [8, 0]
Here the new Document id was not returned, so EclipseLink tries to insert the Document id 0 into both the login table and the joined table for the subtype.
Since I couldn't find any information about not being supposed to use @ReturnInsert for @Id with InheritanceType.JOINED I assume this might be a bug.
Ok, I wasn't aware that since EL 3 it's possible to use @GeneratedValue(strategy = GenerationType.IDENTITY) on Oracle identitiy columns.
So changing from @ReturnInsert to @GeneratedValue(strategy = GenerationType.IDENTITY) does fix my problem. I see EL fetching the Oracle sequence name for the table and upon inserting fetching an id from the sequence.
I am unsure whether to close the issue or not since I cannot judge if the behavior I encountered is still considered a bug or an invalid combination of features.
I'm migrating an application and facing the same issue. I do think it's a bug, but I'm gonna test my application with the @GeneratedValue annotation with Oracle database to see if I can leave the returning annotation aside.
[Edit]
I've tried to make it work with @GeneratedValue annotation but no success. Our application has to work with both oracle and postgresql databases. We were using EL 2.6.4 and everything was working fine.
But now the method buildInsertStatement from class ExpressionQueryMechanism has changed and doesn't get the correct returning fields when building the abstract entity insert.