Home » Eclipse Projects » EclipseLink » JPA 2.0 @EmbeddedId mappings: bug with @MapsId in single-column identifying relationship?
JPA 2.0 @EmbeddedId mappings: bug with @MapsId in single-column identifying relationship? [message #669746] |
Wed, 11 May 2011 07:26  |
Eclipse User |
|
|
|
Hello,
I have the following simple design:
URL GONE
Here the DDL:
CREATE TABLE Countries (
id INTEGER NOT NULL,
iso_code CHAR(2) NOT NULL,
PRIMARY KEY (id),
UNIQUE (iso_code));
CREATE TABLE Zips (
country_code CHAR(2) NOT NULL,
code VARCHAR(10) NOT NULL,
PRIMARY KEY (country_code, code),
CONSTRAINT zips_countries_fk
FOREIGN KEY (country_code)
REFERENCES Countries (iso_code)
ON DELETE NO ACTION
ON UPDATE CASCADE);
The Countries table has an ID as PK. Zips has a multi-column PK and uses a single-column reference to a non-PK column (alternative unique key) iso_code. The latter is the specialty of this design.
EclipseLink has problems mapping them with the following entity classes:
@Entity
@Table(name = "Countries")
public class Country implements Serializable
{
@Id
@Column(name = "id")
private Integer id;
@Column(name = "iso_code")
private String isoCode;
...
}
@Entity
@Table(name = "Zips")
public class Zip implements Serializable
{
@EmbeddedId
private ZipId embeddedId;
@MapsId(value = "countryCode") // outcomment @MapsId to make JPA 1.0 @EmbeddedId work
@ManyToOne
@JoinColumn(name = "country_code", referencedColumnName = "iso_code")
private Country country;
...
}
@Embeddable
public class ZipId implements Serializable
{
@Column(name = "country_code", insertable = false, updatable = false)
private String countryCode;
@Column(name = "code")
private String code;
...
}
Using the entity manager to retrieve a single ZIP entity: Zip zi = em.find(Zip.class, new ZipId("DE", "64846"));
Stack trace:
Entity manager created!
Loaded country = tld.geoareas.model.Country@5bf02b85[id=1,isoCode=AF]
Exception in thread "main" java.lang.IllegalArgumentException: You have provided an instance of an incorrect PK class for this find operation. Class expected : class java.lang.Integer, Class received : class java.lang.String.
at org.eclipse.persistence.internal.jpa.CMP3Policy.createPrimaryKeyFromId(CMP3Policy.java:215)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.findInternal(EntityManagerImpl.java:695)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.find(EntityManagerImpl.java:617)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.find(EntityManagerImpl.java:496)
at tld.geoareas.Main.main(Main.java:38)
I know the JPA doesn't officially support non-PK relationships, but EclipseLink has no problems with mapping these in JPA 1.0 @IdClass syntax and more importantly without the JPA 2.0 @MapsId annotation (basically resulting in JPA 1.0 @EmbeddedId syntax).
So EclipseLink should technically be able to handle this non-JPA mapping but it doesn't.
There are two possibilities now:
1. I'm using the @MapsId annotation incorrectly
2. It's a bug
I know EL should expect a PK column here, but again since it correctly maps other non-PK relationship syntaxes mentioned above, this one should be supported as well.
So, is this an EclipseLink bug? Or is it just the JPA 2.0 spec being more restrictive than JPA 1.0? (just comment the @MapsId annotation and see for yourself)
I'd be glad if the someone (EL maintainers?) could have a look at this problem.
Thanks
[Updated on: Thu, 23 July 2020 04:24] by Moderator
|
|
| | | | | |
Re: JPA 2.0 @EmbeddedId mappings: bug with @MapsId? [message #670998 is a reply to message #670417] |
Mon, 16 May 2011 09:52   |
Eclipse User |
|
|
|
Hello Karsten,
As mentioned, JPA requires the foreign key->primary key, and EclipseLink uses this restriction in determining what the Primary key class should look like when you are using the Derrived Id JPA 2.0 feature. As mentioned, fill a bug to have this behavior changed if you wish. It was done likely because the primary key class is entirely a JPA construct - EclipseLink internally uses collections of values as the primary key, not a pk class.
The restriction is only in the CMP3Policy class, which is mostly only used for the em.find method to convert the JPA pk class into a vector of values. If you can avoid it, you will not have any problems. Or, you can use the em.find passing in a vector of values instead of your JPA pk class, avoiding the conversion.
Regards,
Chris
edit: The policy is not more restrictive. When specifying mapsId it uses the Derrived ID which means it must go to the reference class to get the value instead of using the value in the object like it would in JPA 1.0. This relationship traversal is what has the expectation that the field will be the primary key field. As mentioned, file a bug to have this changed.
[Updated on: Mon, 16 May 2011 09:55] by Moderator
|
|
| | | | |
Goto Forum:
Current Time: Sat Jul 12 01:41:02 EDT 2025
Powered by FUDForum. Page generated in 0.05841 seconds
|