[hibernate-issues] [Hibernate-JIRA] Updated: (ANN-548) Fails to map a FK pointing to a non PK whose columns are held by properies in component
Emmanuel Bernard (JIRA)
noreply at atlassian.com
Sat Feb 10 02:24:41 EST 2007
[ http://opensource.atlassian.com/projects/hibernate/browse/ANN-548?page=all ]
Emmanuel Bernard updated ANN-548:
---------------------------------
Component: binder
Summary: Fails to map a FK pointing to a non PK whose columns are held by properies in component (was: Joins break when using composite primary key classes)
Priority: Minor (was: Major)
So I looked at the issue,
The problem is that HAN does not handle well FK pointing to non primary keys where:
- each non PK column is not referenced by a property (ie property handling multiple columns)
- the property referencing the PK column(s) is part of a component (ie not a top level property)
Your case belongs in case 2. Unfortunately, a fix, if possible, would be very complex. As I said in the forum, your case (fk pointing to a part of the pk, this part being unique) is pretty uncommon.
If someone wants to give it a try it is related to BinderHelper.createSyntheticPropertyReference() in the NON_PK_REFERENCE case: it would be better to redesign this area from scratch.
> Fails to map a FK pointing to a non PK whose columns are held by properies in component
> ---------------------------------------------------------------------------------------
>
> Key: ANN-548
> URL: http://opensource.atlassian.com/projects/hibernate/browse/ANN-548
> Project: Hibernate Annotations
> Type: Bug
> Components: binder
> Versions: 3.2.1, 3.2.2
> Environment: JBoss 4.0.5.GA w/ Hibernate 3.2.2 and Annoations 3.2.2 (from SVN). Also reproduced w/ JBoss 4.0.5.GA w/ stock annotations, hibernate, and entity manager, unmodified. The attached test-case was run against MSSQL 2000 but is trivial to point at another database. The issue was also reproduced on a OpenEdge Progress 10.1A database.
> Reporter: Vincent Jenks
> Priority: Minor
> Attachments: CarBean.java, Carz.java, Lotz.java
>
>
> Joins break when using composite primary key classes
> JBoss 4.0.5.GA w/ Hibernate 3.2.2 and Annoations 3.2.2 (from SVN). Also reproduced w/ JBoss 4.0.5.GA w/ stock annotations, hibernate, and entity manager, unmodified. The attached test-case was run against MSSQL 2000 but is trivial to point at another database. The issue was also reproduced on a OpenEdge Progress 10.1A database.
> In a case where there are composite keys on one (or each) side of a relationship, Hibernate cannot join the entities together if all of the primary key fields are not used in the relationship.
> A (very) simple example, two entities Carz and Lotz (pardon the names, it's simply cars and car lots):
> @Entity
> @Table(name="car")
> public class Carz implements Serializable
> {
> @Id
> private Integer id;
>
> @Column(name="make", nullable=false)
> private String make;
> @Column(name="model", nullable=false)
> private String model;
> @Column(name="manufactured", nullable=false)
> @Temporal(TemporalType.TIMESTAMP)
> private Date manufactured;
>
> @ManyToOne(fetch=FetchType.LAZY)
> @JoinColumns //Hibernate docs state that @JoinColumns must be used since Lotz has composite PK, a single @JoinColumn does not deploy anyhow
> ({
> @JoinColumn(name="loc_code", referencedColumnName="loc_code", insertable=false, updatable=false)
> })
> private Lotz lot;
> ...........................
> }
> @Entity
> @Table(name="lot")
> public class Lotz implements Serializable
> {
> @EmbeddedId
> protected LotzPK lotPK;
>
> @Column(name="name", nullable=false)
> private String name;
> @Column(name="location", nullable=false)
> private String location;
> @OneToMany(mappedBy="lot", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
> private List<Carz> cars;
> ...........................
> }
> @Embeddable
> public class LotzPK implements Serializable
> {
> @Column(name="id", nullable=false)
> private Integer id;
>
> @Column(name="loc_code", nullable=false)
> private String locCode;
> ...........................
> }
> In this case I need a one-to-many relationship on Carz.id = Lotz.locCode. However, there doesn't appear to be a way to do this.
> When this is deployed, this exception occurs:
> org.hibernate.AnnotationException: Column name id of hqb.model.Lotz not found in JoinColumns.referencedColumnName
> at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:306)
> at org.hibernate.cfg.FkSecondPass.doSecondPass(FkSecondPass.java:64)
> at org.hibernate.cfg.AnnotationConfiguration.processFkSecondPassInOrder(AnnotationConfiguration.java:433)
> at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:287)
> at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1115)
> at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1211)
> at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:154)
> at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:847)
> at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:385)
> at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:126)
> at org.jboss.ejb3.entity.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:264)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at org.jboss.ejb3.ServiceDelegateWrapper.startService(ServiceDelegateWrapper.java:102)
> at org.jboss.system.ServiceMBeanSupport.jbossInternalStart(ServiceMBeanSupport.java:289)
> at org.jboss.system.ServiceMBeanSupport.jbossInternalLifecycle(ServiceMBeanSupport.java:245)
> at sun.reflect.GeneratedMethodAccessor263.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> ...........................
> I can deploy the app if I map both fields in the Lotz PK class like so:
> @Entity
> @Table(name="car")
> public class Carz implements Serializable
> {
> @Id
> private Integer id;
> ...........................
>
> @ManyToOne(fetch=FetchType.LAZY)
> @JoinColumns
> ({
> @JoinColumn(name="loc_code", referencedColumnName="loc_code", insertable=false, updatable=false),
> @JoinColumn(name="", referencedColumnName="id", insertable=false, updatable=false) //INCORRECTLY DEFINED RELATIONSHIP!
> })
> private Lotz lot;
> ...........................
> }
> But obviously this is no good, it generates bad SQL at runtime:
> /* select
> c
> from
> Carz c
> left join
> fetch c.lot */ select
> carz0_.id as id198_0_,
> lotz1_.id as id199_1_,
> lotz1_.loc_code as loc2_199_1_,
> carz0_.make as make198_0_,
> carz0_.model as model198_0_,
> carz0_.manufactured as manufact4_198_0_,
> carz0_.lot_id as lot5_198_0_,
> carz0_.loc_code as loc6_198_0_, --no such column...
> lotz1_.name as name199_1_,
> lotz1_.location as location199_1_
> from
> car carz0_
> left outer join
> lot lotz1_
> on carz0_.lot_id=lotz1_.id --oops! Hibernate defaulted a relationship here...
> and carz0_.loc_code=lotz1_.loc_code
> In reality, this is the SQL I'm trying to achieve, by repairing the above query manually:
> select
> carz0_.id as id198_0_,
> lotz1_.id as id199_1_,
> lotz1_.loc_code as loc2_199_1_,
> carz0_.make as make198_0_,
> carz0_.model as model198_0_,
> carz0_.manufactured as manufact4_198_0_,
> carz0_.loc_code as loc6_198_0_,
> lotz1_.name as name199_1_,
> lotz1_.location as location199_1_
> from
> car carz0_
> left outer join
> lot lotz1_
> on carz0_.loc_code=lotz1_.loc_code
> This is consistent w/ the EJB 3.0 spec (and Glassfish+Toplink) but that's only because the spec doesn't define exacltly how to handle this. However, that being said, this seems important enough for Hibernate to be able to manage?
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
More information about the hibernate-issues
mailing list