]
Anne Buit commented on HHH-6221:
--------------------------------
Two more topics on the Hibernate forum about this issue:
Hibernate throws AnnotationException on column used by multiple
overlapping foreign keys
----------------------------------------------------------------------------------------
Key: HHH-6221
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-6221
Project: Hibernate Core
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
Priority: Critical
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: