问题描述
我们正在将基于xml的旧配置转换为基于Annotation的配置 情况 有一个类被注释为
@Embeddable(ParentPk.java)
,另一个类扩展了这个类,它是 @Embeddable(ChildPk.java )
,这个ChildPk.java被用作 SomeOwnerClass.java
中的复合主键,它与另一个类 SomeChildTable.java
并倾向于使用父类 ChildPk.java
ChildPk.java
中,每一件事都可以正常工作。
以下是 SomeOwnerClass.java
的代码片段,它指 col1 和 col2
> @OneToMany(orphanRemoval = true,fetch = FetchType.EAGER)
> @Cascade(value = {CascadeType.ALL,CascadeType.SAVE_UPDATE})
> @Fetch(FetchMode.JOIN)
> @JoinColumn({
> @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>();
这种情况的解决方案是什么?
ParentPk.java
@Embeddable
和
公共类ParentPk实现Serializable {
@Column(name =COL_1)
private String col1;
@Column(ame =COL_2)
private String col2;
ChildPk.java p>
@Embeddable
public class ChildPk extends ParentPk implements Serializable {
@Column(name = COL_3)
私人字符串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>();
}
例外
org.hibernate.MappingException:无法在org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn。)中的SomeOwnerClass
中查找具有逻辑名称:COL_1的列。
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)
位于org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
位于org.hibernate.cfg。 Configuration.originalSecondPassCompile(Configuration.ja va:1695)
在org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
在org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
在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 )
其他详细信息
我试图映射基于xml配置到基于注解的配置下面是旧的基于xml的配置,在继承方面工作正常。
ChildPk.java转换为@Embedable,它扩展了ParentPk.java
< class name =Som eOwnerClassDetailtable =FOO_DETAIL>
< composite-id class =ChildPk
name =childPk>
< key-property name =col1column =COL_1type =java.lang.Long/>
< key-property name =col2column =COL_2length =32/>
< key-property name =col3column =COL_3length =3/>
< / composite-id>
< / class>上面的映射col1和col2中的
是从ParentPk.java继承的,如果ChildPk用作外键在xml映射中键入SomeOwnerClass.java,但不在注释映射中。
我无法更改我的类的结构,因为它是传统应用程序。 b
$ bSomeOwnerClass.java
< set name =someDetailKeycascade =all,delete-orphan,save-updatelazy =falsefetch =join>
< key foreign-key =FOO_Foreign_Key>
< column name =COL_1/>
< column name =COL_2/>
< column name =COL_3/>
< / key>
< / set>
解决方案您可以在
所以,例如:@Embeddable
类之间实现继承。你只需要用@MappedSuperclass
来注释父类。@Embeddable
@MappedSuperclass
public class Parent {
@Basic
private String parentProperty;
// ... getters / setters
}
@Embeddable
public class Child extends Parent {
@Basic
private String childProperty;
// ... getters / setters
}
这样Hibernate(用5.x测试)将在 parentProperty
childProperty
> Child class。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 inSomeOwnerClass.java
, Which have foreign relation with another classSomeChildTable.java
and tends to use properties col1 and col2 which are available in parent class ofChildPk.java
but when query is executed hibernate does not finds col1 and col2 rather if I copy col1 and col2 inChildPk.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 DetailI 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>
解决方案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
andchildProperty
correctly in theChild
class.这篇关于Hibernate @Embeddable类扩展了另一个@Embeddable类,找不到@OneToMany映射的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!