]
Karsten Wutzke commented on HHH-6221:
-------------------------------------
Bug still present in all Hibernate 4.x version to date. Please upgrade to blocker since
there's no way to workaround this but to change the DB. The JPA reference
implementation EclipseLink handles this without any problems.
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: