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 11:26 |
Karsten Wutzke Messages: 124 Registered: July 2009 |
Senior Member |
|
|
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 08:24] Report message to a moderator
|
|
| | | |
Re: JPA 2.0 @EmbeddedId mappings: bug with @MapsId? [message #670417 is a reply to message #670302] |
Sat, 14 May 2011 00:18 |
Karsten Wutzke Messages: 124 Registered: July 2009 |
Senior Member |
|
|
Hello Chris,
I'm not sure if I really got your point (or vice versa). The mappings I posted work when outcommenting the @MapsId annotation and EL fails when the @MapsId(value = "countryCode") is present. It doesn't make any sense, does it?
Would it help to provide an SSCCE here?
The use of the @MapsId annotation basically turns the mapping into a JPA 2.0 derived identity, but why should the newer JPA 2.0 mapping type be more restrictive than the old (again given the fact that EL correctly handles the mappings without the @MapsId annotation)?
Even though the JPA doesn't support relationships to non-PK columns doesn't mean they are forbidden in derived identities. It's up to EL to implement this as an optional feature. EL currently handles non-PK relationships pretty well, so why not support them in derived identities, too? The technology is already there I'd think.
For your reference please also see http://www.kawoolutions.com/Technology/JPA,_Hibernate,_and_C o./Relationships_to_Non-Primary_Key_Columns for a case study of relationships to non-PK columns. (it's pretty new and there will likely be things to be corrected)
Karsten
[Updated on: Sun, 15 May 2011 18:44] Report message to a moderator
|
|
| |
Re: JPA 2.0 @EmbeddedId mappings: bug with @MapsId? [message #670998 is a reply to message #670417] |
Mon, 16 May 2011 13:52 |
Chris Delahunt Messages: 1389 Registered: July 2009 |
Senior Member |
|
|
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 13:55] Report message to a moderator
|
|
| | | | |
Goto Forum:
Current Time: Mon Dec 09 20:13:02 GMT 2024
Powered by FUDForum. Page generated in 0.28060 seconds
|