[hibernate-issues] [Hibernate-JIRA] Updated: (HHH-6221) Hibernate throws AnnotationException on column used by multiple overlapping foreign keys

Steve Ebersole (JIRA) noreply at atlassian.com
Fri Mar 2 11:57:48 EST 2012


     [ https://hibernate.onjira.com/browse/HHH-6221?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

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: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list