Home » Eclipse Projects » EclipseLink » @EmbeddedId in conjunction with InheritanceType.JOINED does not generate PK-Field
@EmbeddedId in conjunction with InheritanceType.JOINED does not generate PK-Field [message #728691] |
Fri, 23 September 2011 16:45 |
Hannes Messages: 11 Registered: September 2011 |
Junior Member |
|
|
Hello,
I have a class, using @EmbeddedId as primary key:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@Table(name="PAE")
@DiscriminatorColumn(name="DTYPE", discriminatorType=DiscriminatorType.STRING,length=20)
@DiscriminatorValue("R")
public class PersistentAccountancyEntry implements AccountancyEntry {
@EmbeddedId
@AttributeOverride(name="id", column=@Column(name="ENTRY_ID"))
private AccountancyEntryIdentifier accountancyEntryIdentifier;
And a subclass of that class:
@Entity
@Table(name="PPE")
@DiscriminatorValue("P")
public class ProductPaymentEntry extends PersistentAccountancyEntry
{
@Embedded
@AttributeOverride(name = "id", column = @Column(name = "ORDER_ID"))
private OrderIdentifier orderIdentifier;
@Embedded
@AttributeOverride(name = "id", column = @Column(name = "UID"))
private UserIdentifier userIdentifier;
Which results in tables being generated as follows:
[EL Fine]: Connection(941535430)--DROP TABLE PAE
[EL Fine]: Connection(941535430)--CREATE TABLE PAE (DTYPE VARCHAR(20), DATE TIMESTAMP, DESCRIPTION VARCHAR(255), VALUE BLOB(2147483647), ENTRY_ID VARCHAR(255))
[EL Fine]: Connection(941535430)--DROP TABLE PPE
[EL Fine]: Connection(941535430)--CREATE TABLE PPE (ENTRY_ID VARCHAR(255) NOT NULL, ORDER_ID VARCHAR(255), UID VARCHAR(255) NOT NULL, PRIMARY KEY (ENTRY_ID, UID))
Notably, ENTRY_ID is not a primary key field on table PAE, instead the table PPE has a composite primary key of ENTRY_ID and UID. UID is just a foreign key, not a composite primary key. (OrderIdentifier is an @EmbeddedId in an entirely different class.)
All this would matter much, but some queries fail:
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<PersistentAccountancyEntry> q = cb
.createQuery(PersistentAccountancyEntry.class);
Root<PersistentAccountancyEntry> r = q
.from(PersistentAccountancyEntry.class);
Predicate p = cb.between(r.get(PersistentAccountancyEntry_.date),
from.toDate(), to.toDate());
q.where(p);
TypedQuery<PersistentAccountancyEntry> tq = em.createQuery(q);
[EL Warning]: 2011-09-23 18:38:44.388--UnitOfWork(1237880619)--Exception [EclipseLink-6044] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.QueryException
Exception Description: The primary key read from the row [ArrayRecord(
PAE.DTYPE => R
PAE.DATE => 2011-09-23 18:38:37.219
PAE.DESCRIPTION => null
PAE.VALUE => [B@6153e0c0
PAE.ENTRY_ID => 45aabaaf-cf87-4261-b0b0-f13a8b5e5ead)] during the execution of the query was detected to be null. Primary keys must not contain null.
Query: ReadAllQuery(referenceClass=PersistentAccountancyEntry sql="SELECT DISTINCT DTYPE FROM PAE WHERE (DATE BETWEEN ? AND ?)")
Now, ENTRY_ID should be the primary key field, and it is obviously not null. What am I doing wrong?
|
|
| | | | |
Re: @EmbeddedId in conjunction with InheritanceType.JOINED does not generate PK-Field [message #732347 is a reply to message #731980] |
Tue, 04 October 2011 14:52 |
Hannes Messages: 11 Registered: September 2011 |
Junior Member |
|
|
I removed the InheritanceStrategy, so the table generation defaults to single table. This seems to work, if all @EmbeddedIds and @Embeddables are annotated with @AttributeOverrides.
The code now looks like:
@Entity
public class PersistentAccountancyEntry implements AccountancyEntry {
@EmbeddedId
@AttributeOverride(name = "id", column = @Column(name = "ENTRY_ID", nullable = false))
private AccountancyEntryIdentifier accountancyEntryIdentifier = new AccountancyEntryIdentifier();
...
@Entity
public class ProductPaymentEntry extends PersistentAccountancyEntry {
/**
* The <code>OrderIdentifier</code> to which this
* <code>ProductPaymentEntry</code> refers to.
*/
@Embedded
@AttributeOverride(name = "id", column = @Column(name = "ORDER_ID", nullable = true))
private OrderIdentifier orderIdentifier;
/**
* The <code>UserIdentifier</code> to which this
* <code>ProductPaymentEntry</code> refers to.
*/
@Embedded
@AttributeOverride(name = "id", column = @Column(name = "USER_ID", nullable = true))
private UserIdentifier userIdentifier;
...
Resulting in:
[EL Fine]: Connection(1085171660)--CREATE TABLE PERSISTENTACCOUNTANCYENTRY (DTYPE VARCHAR(31), DATE TIMESTAMP, DESCRIPTION VARCHAR(255), VALUE BLOB(2147483647), ENTRY_ID VARCHAR(255) NOT NULL, PAYMENTMETHOD BLOB(2147483647), ORDER_ID VARCHAR(255), USER_ID VARCHAR(255), PRIMARY KEY (ENTRY_ID))
It seems using @Embeddable annotation and @MappedSuperclass simultaneously allows for correct @Embeddable inheritance in this scenario. Removing the identifier hierarchy results in a lot of code duplication for equals() and hashcode() methods of the identifiers, which I would like to avoid. SalespointIdentifier should be used as PK itself (@EmbeddableId); this is why it is annotated with @Embeddable. And with the @MappedSuperclass annotation, sub class instances, annotated with @Embedded generate also columns (which does not work otherwise).
|
|
|
Re: @EmbeddedId in conjunction with InheritanceType.JOINED does not generate PK-Field [message #732821 is a reply to message #731980] |
Tue, 04 October 2011 14:52 |
Hannes Messages: 14 Registered: March 2011 |
Junior Member |
|
|
I removed the InheritanceStrategy, so the table generation defaults to single table. This seems to work, if all @EmbeddedIds and @Embeddables are annotated with @AttributeOverrides.
The code now looks like:
@Entity
public class PersistentAccountancyEntry implements AccountancyEntry {
@EmbeddedId
@AttributeOverride(name = "id", column = @Column(name = "ENTRY_ID", nullable = false))
private AccountancyEntryIdentifier accountancyEntryIdentifier = new AccountancyEntryIdentifier();
...
@Entity
public class ProductPaymentEntry extends PersistentAccountancyEntry {
/**
* The <code>OrderIdentifier</code> to which this
* <code>ProductPaymentEntry</code> refers to.
*/
@Embedded
@AttributeOverride(name = "id", column = @Column(name = "ORDER_ID", nullable = true))
private OrderIdentifier orderIdentifier;
/**
* The <code>UserIdentifier</code> to which this
* <code>ProductPaymentEntry</code> refers to.
*/
@Embedded
@AttributeOverride(name = "id", column = @Column(name = "USER_ID", nullable = true))
private UserIdentifier userIdentifier;
...
Resulting in:
[EL Fine]: Connection(1085171660)--CREATE TABLE PERSISTENTACCOUNTANCYENTRY (DTYPE VARCHAR(31), DATE TIMESTAMP, DESCRIPTION VARCHAR(255), VALUE BLOB(2147483647), ENTRY_ID VARCHAR(255) NOT NULL, PAYMENTMETHOD BLOB(2147483647), ORDER_ID VARCHAR(255), USER_ID VARCHAR(255), PRIMARY KEY (ENTRY_ID))
It seems using @Embeddable annotation and @MappedSuperclass simultaneously allows for correct @Embeddable inheritance in this scenario. Removing the identifier hierarchy results in a lot of code duplication for equals() and hashcode() methods of the identifiers, which I would like to avoid. SalespointIdentifier should be used as PK itself (@EmbeddableId); this is why it is annotated with @Embeddable. And with the @MappedSuperclass annotation, sub class instances, annotated with @Embedded generate also columns (which does not work otherwise).
|
|
| |
Goto Forum:
Current Time: Fri Apr 26 18:57:41 GMT 2024
Powered by FUDForum. Page generated in 0.02984 seconds
|