]
Steve Ebersole updated HHH-6221:
--------------------------------
Priority: Major (was: Critical)
Fix Version/s: 5.0.0
There is already work under way for 5.0 to fix the underlying limitation here. I
can't commit resources to this for any earlier releases. If someone wants to work on
support for this against 4.1 (currently master atm) I'd be willing to look at
integrating pull requests which address this. Other than that, this will have to wait for
5.0.
Hibernate throws AnnotationException on column used by multiple
overlapping foreign keys
----------------------------------------------------------------------------------------
Key: HHH-6221
URL:
https://hibernate.onjira.com/browse/HHH-6221
Project: Hibernate ORM
Issue Type: Bug
Components: annotations, core, entity-manager
Affects Versions: 3.6.0
Environment: Hibernate 3.6.0, HSQLDB 2, JavaSE (probably all Hibernate versions
to date affected)
Reporter: Karsten Wutzke
Fix For: 5.0.0
Attachments: overlapping-fks-hib-broken.zip
Here's a view of the design:
!http://www.kawoolutions.com/media/postareas-min.png!
Simple logic: two tables use composite PKs and use a country_code column in the PK.
PostAreas is a simple join table so its PK is comprised of the two linked tables' PK
columns. Problem: both FKs in PostAreas use country_code to produce an overlap.
This is per se nothing special, but in the context of JPA it is: there may be only one
writable mapping in the @JoinColumn annotations, all other must be set to read-only, that
is _insertable = false, updatable = false_.
Here are the (incomplete) mappings (full SSCCE attached):
{code:java}
@Entity
@Table(name = "Zips")
@IdClass(value = ZipId.class)
public class Zip implements Serializable
{
@Id
@Column(name = "country_code")
private String countryCode;
@Id
@Column(name = "code")
private String code;
...
}
{code}
{code:java}
public class ZipId implements Serializable
{
private String countryCode;
private String code;
...
}
{code}
{code:java}
@Entity
@Table(name = "Cities")
@IdClass(value = CityId.class)
public class City implements Serializable
{
@Id
@Column(name = "country_code")
private String countryCode;
@Id
@Column(name = "state_code")
private String stateCode;
@Id
@Column(name = "name")
private String name;
...
}
{code}
{code:java}
public class CityId implements Serializable
{
private String countryCode;
private String stateCode;
private String name;
...
}
{code}
{code:java}
@Entity
@Table(name = "PostAreas")
@IdClass(value = PostAreaId.class)
public class PostArea implements Serializable
{
@Id
@Column(name = "country_code", insertable = false, updatable = false)
private String countryCode;
@Id
@Column(name = "state_code", insertable = false, updatable = false)
private String stateCode;
@Id
@Column(name = "zip_code", insertable = false, updatable = false)
private String zipCode;
@Id
@Column(name = "city_name", insertable = false, updatable = false)
private String cityName;
@ManyToOne
@JoinColumns(value = {
@JoinColumn(name = "country_code", referencedColumnName =
"country_code"),
@JoinColumn(name = "zip_code", referencedColumnName =
"code")
})
private Zip zip;
@ManyToOne
@JoinColumns(value = {
@JoinColumn(name = "country_code", referencedColumnName =
"country_code", insertable = false, updatable = false), // <- !!!
@JoinColumn(name = "state_code", referencedColumnName =
"state_code"),
@JoinColumn(name = "city_name", referencedColumnName =
"name")
})
private City city;
...
}
{code}
{code:java}
public class PostAreaId implements Serializable
{
private String countryCode;
private String stateCode;
private String zipCode;
private String cityName;
...
}
{code}
Looking at PostArea.city (*scroll down in the PostArea code box!*): the @JoinColumn for
country_code is set to read-only on City and to writable on Zip. However, when running
this from a JavaSE test app Hibernate fails with an AnnotationException:
{code}
Exception in thread "main" javax.persistence.PersistenceException:
[PersistenceUnit: postareas] Unable to configure EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:374)
at
org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
at tld.postareas.Main.main(Main.java:38)
Caused by: org.hibernate.AnnotationException: Mixing insertable and non insertable
columns in a property is not allowed: tld.postareas.model.PostAreacity
at org.hibernate.cfg.Ejb3Column.checkPropertyConsistency(Ejb3Column.java:563)
at org.hibernate.cfg.AnnotationBinder.bindManyToOne(AnnotationBinder.java:2703)
at
org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1600)
at
org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:796)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:707)
at
org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3977)
at
org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3931)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1368)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1477)
at
org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1096)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:278)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:362)
... 4 more
{code}
When mapping a table that uses the same column in two or more foreign keys, only one of
the relationships' @JoinColumn annotations may be tagged as writable. However, mixing
read-only and writable in a multi-column relationship *must* be supported.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: