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

17,376

Solution 1

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.

Solution 2

Hibernate doesn't support inheritance of @Embeddable component:

An embeddable object cannot be directly persisted, or queried, it can only be persisted or queried in the context of its parent. An embeddable object does not have an id or table. The JPA spec does not support embeddable objects having inheritance, although some JPA providers may allow this.

Java_Persistence/Embeddables.

The JPA spec does not support embeddable objects having inheritance
So you cannot make use of Inheritance in @Embeddable.

You can try to get it done by having the parent id as a property of the child id.

Share:
17,376

Related videos on Youtube

Yahya Arshad
Author by

Yahya Arshad

My name is Yahya Arshad, I 'm a software engineer and my goal is to be a software architect. My email to contact is [email protected] and skype yahya.arshad Android Table Create Using Annotation: Android Table Create

Updated on June 07, 2022

Comments

  • Yahya Arshad
    Yahya Arshad about 2 years

    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>
    

  • Yahya Arshad
    Yahya Arshad about 9 years
    Thank you saif for your reply but same class relation works fine in xml based configuration i need its alternate in annotation. I have added additional detail "Additional Detail"
  • Andreas Covidiot
    Andreas Covidiot over 8 years
    +1 because its a valid answer if it means there should not (generally) be an annotation for this available
  • Steve Ebersole
    Steve Ebersole almost 6 years
    This is the proper answer. JPA does not define explicit support for inheritance of embeddables. However Hibernate does support inheritance of embeddables
  • Steve Ebersole
    Steve Ebersole almost 6 years
    Hit enter instead of shift+enter above :( This is the proper answer. JPA does not define explicit support for inheritance of embeddables. However Hibernate does support inheritance of embeddables using @MappedSuperclass to define its super-type. IMO we should add support for extending another embeddable as well - hibernate.atlassian.net/browse/HHH-12790
  • Steve Ebersole
    Steve Ebersole almost 6 years
    This answer is simply incorrect. As mentioned in my comment on the answer below, Hibernate does in fact "support inheritance of @Embeddable".
  • cljk
    cljk over 5 years
    wokrs in wilflfy 15
  • RoutesMaps.com
    RoutesMaps.com almost 3 years
    Thank you. By this instruction I got in JPA generated table of PostgreSQL database Mapped from Superclass columns with strange "Read-only: No Corresponding table column" DBeaver information. What does that mean?