Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
511 views
in Technique[技术] by (71.8m points)

inheritance - Hibernate @Embeddable class which extends another @Embeddable class, Properties not found for @OneToMany mapping

We are translating old xml based configuration to Annotation based configuration

Situation

There is a class which is annotated as @Embeddable(ParentPk.java), another class extends this class which is @Embeddable(ChildPk.java), this ChildPk.java is used as composite primary key in SomeOwnerClass.java, Which have foreign relation with another class SomeChildTable.java and tends to use properties col1 and col2 which are available in parent class of ChildPk.java but when query is executed hibernate does not finds col1 and col2 rather if I copy col1 and col2 in ChildPk.java from parent class every thing works fine.

Below is code snippet of SomeOwnerClass.java which refers to col1 and col2

>  @OneToMany(orphanRemoval = true, fetch=FetchType.EAGER)
>        @Cascade(value = {CascadeType.ALL,CascadeType.SAVE_UPDATE})
>        @Fetch(FetchMode.JOIN)
>        @JoinColumns({
>        @JoinColumn(name="COL_1",insertable=false,updatable=false,referencedColumnName="COL_1"),
>        @JoinColumn(name="COL_2",insertable=false,updatable=false,referencedColumnName="COL_2"),
>        @JoinColumn(name="COL_3",insertable=false,updatable=false,referencedColumnName="COL_3"),
>     })    private Set<SomeChildTable> collection = new
> HashSet<SomeChildTable>();

Any solution for this situation?

ParentPk.java

 @Embeddable
    public class ParentPk implements Serializable  {

        @Column(name="COL_1")
        private String col1;

        @Column(ame="COL_2")
        private String col2;

    }

ChildPk.java

@Embeddable
public class ChildPk extends ParentPk implements Serializable  {

    @Column(name="COL_3")
    private String col3;
}

SomeOwnerClass.java

@Entity
@Table(name="FOO")
public class SomeOwnerClass implements Serializable  {

    @EmbeddedId
       @AttributeOverrides({@AttributeOverride(name="col1", column=@Column(name="COL_1",length=38))})
        private ChildPk childPk = new ChildPk();

         @OneToMany(orphanRemoval = true, fetch=FetchType.EAGER)
         @Cascade(value = {CascadeType.ALL,CascadeType.SAVE_UPDATE})
         @Fetch(FetchMode.JOIN)
         @JoinColumns({
         @JoinColumn(name="COL_1",insertable=false,updatable=false,referencedColumnName="COL_1"),
         @JoinColumn(name="COL_2",insertable=false,updatable=false,referencedColumnName="COL_2"),
         @JoinColumn(name="COL_3",insertable=false,updatable=false,referencedColumnName="COL_3"),
      })
    private Set<SomeChildTable> collection = new HashSet<SomeChildTable>();
}

Exception

org.hibernate.MappingException: Unable to find column with logical name: COL_1 in SomeOwnerClass
    at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:587)
    at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:258)
    at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1451)
    at org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:864)
    at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:779)
    at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:728)
    at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
    at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1695)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
    at com.foo.mypackage.ParentHibernateUtil.initiateSessionFactory(ParentHibernateUtil.java:112)
    at com.foo.mypackage.ParentHibernateUtil.getSessionFactory(ParentHibernateUtil.java:131)
    at com.foo.mypackage.GenericHibernateDAO.getSession(GenericHibernateDAO.java:36)
    at com.foo.mypackage.GenericHibernateDAO.beginTransaction(GenericHibernateDAO.java:63)
    at com.foo.mypackage.MarsTest.main(MyTest.java:22)

Additional Detail I have tried to map xml based configuration to annotation based configuration below is old xml based configuration which works fine in term of inheritence.

ChildPk.java converted to @Embedable which extends ParentPk.java

<class name="SomeOwnerClassDetail" table="FOO_DETAIL">

        <composite-id class="ChildPk"
            name="childPk">
            <key-property name="col1" column="COL_1"  type="java.lang.Long"/>
            <key-property name="col2" column="COL_2" length="32"/>
            <key-property name="col3" column="COL_3" length="3"/>
        </composite-id>
    </class>

in above mapping col1 and col2 are inherited from ParentPk.java which are accessible if ChildPk is used as foreign key in SomeOwnerClass.java in xml mapping but not in annotated mapping.

I can't change structure of my class as it is legacy application.

SomeOwnerClass.java

<set name="someDetailKey" cascade="all,delete-orphan,save-update" lazy="false" fetch="join"  > 
        <key foreign-key="FOO_Foreign_Key" >
            <column name="COL_1"/>
            <column name="COL_2"/>
            <column name="COL_3"/>
        </key>
        <one-to-many class="ChildPk" />
    </set>

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can implement inheritance between @Embeddable classes. You just have to annotate the parent class with @MappedSuperclass too.

So, e.g.:

@Embeddable
@MappedSuperclass
public class Parent {
    @Basic
    private String parentProperty;

    // ... getters/setters
}

@Embeddable
public class Child extends Parent {
    @Basic
    private String childProperty;

    // ... getters/setters
}

This way Hibernate (tested with 5.x) will map both parentProperty and childProperty correctly in the Child class.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...