我有两个名为“Padre”和“Figlio”的实体 Padre是老板,Figlio是小孩 Padre的主键有两列,PADREK1和PADREK2,都是CHAR(20) Figlio的主键有四列: PADREPADREK1(外国)CHAR(20) PADREPADREK2(外国)CHAR(20) FIGLIOK1 CHAR(20) FIGLIOK2 CHAR(20)
这是我的实体类的代码
public class PadreBean extends BaseEntityBean3 implements Serializable { @EmbeddedId PadrePK iPadrePK; @Column(name = "DESCRIPTION") private String iDescription; @Column(name = "ABSUNIQUEID") private long iABSUniqueId; @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinColumns( { @JoinColumn(name = "ABSOUTQUEUENAME", nullable = true) }) private ABSOutQueueBean iAbsOutQueueBean; @OneToMany(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "PADREPADREK1", referencedColumnName = "PADREK1"), @JoinColumn(name = "PADREPADREK2", referencedColumnName = "PADREK2") }) List iFiglioBeans; ......
iFiglioBeans是孩子们的集合
问题是: 如果Padre的主键列都使用全部20个字符填充,则一切正常; id padre的主键列未完全填充Hibernate会加载集合 但加载后它会清除其内容。
我已经激活了Hibernate日志记录,当我的代码访问子集合时,我看到:
[org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) Obtaining JDBC connection [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) Obtained JDBC connection [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Result set contains (possibly empty) collection: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1, iPadreK1=p1}] [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Result set row: 0 [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Result row: EntityKey[com.dat.abs.run.FiglioBean#component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=1 , iPadrePadreK1=p1 , iFiglioK1=1 , iPadrePadreK2=p1 }] [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Found row of collection: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1 , iPadreK1=p1 }] [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Result set row: 1 [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Result row: EntityKey[com.dat.abs.run.FiglioBean#component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=f1 , iPadrePadreK1=p1 , iFiglioK1=f1 , iPadrePadreK2=p1 }] [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Found row of collection: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1 , iPadreK1=p1 }] [org.hibernate.engine.internal.TwoPhaseLoad] (http-localhost/127.0.0.1:8080-1) Resolving associations for [com.dat.abs.run.FiglioBean#component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=1 , iPadrePadreK1=p1 , iFiglioK1=1 , iPadrePadreK2=p1 }] [org.hibernate.engine.internal.TwoPhaseLoad] (http-localhost/127.0.0.1:8080-1) Done materializing entity [com.dat.abs.run.FiglioBean#component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=1 , iPadrePadreK1=p1 , iFiglioK1=1 , iPadrePadreK2=p1 }] [org.hibernate.engine.internal.TwoPhaseLoad] (http-localhost/127.0.0.1:8080-1) Resolving associations for [com.dat.abs.run.FiglioBean#component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=f1 , iPadrePadreK1=p1 , iFiglioK1=f1 , iPadrePadreK2=p1 }] [org.hibernate.engine.internal.TwoPhaseLoad] (http-localhost/127.0.0.1:8080-1) Done materializing entity [com.dat.abs.run.FiglioBean#component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=f1 , iPadrePadreK1=p1 , iFiglioK1=f1 , iPadrePadreK2=p1 }] [org.hibernate.engine.loading.internal.CollectionLoadContext] (http-localhost/127.0.0.1:8080-1) 2 collections were found in result set for role: com.dat.abs.run.PadreBean.iFiglioBeans [org.hibernate.engine.loading.internal.CollectionLoadContext] (http-localhost/127.0.0.1:8080-1) Collection fully initialized: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1, iPadreK1=p1}] [org.hibernate.engine.loading.internal.CollectionLoadContext] (http-localhost/127.0.0.1:8080-1) Collection fully initialized: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1 , iPadreK1=p1 }] [org.hibernate.engine.loading.internal.CollectionLoadContext] (http-localhost/127.0.0.1:8080-1) 2 collections initialized for role: com.dat.abs.run.PadreBean.iFiglioBeans [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) Releasing JDBC connection [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) Released JDBC connection [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) Done loading collection [org.hibernate.event.internal.AbstractFlushingEventListener] (http-localhost/127.0.0.1:8080-1) Processing flush-time cascades [org.hibernate.event.internal.AbstractFlushingEventListener] (http-localhost/127.0.0.1:8080-1) Dirty checking collections [org.hibernate.engine.internal.Collections] (http-localhost/127.0.0.1:8080-1) Collection found: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1, iPadreK1=p1}], was: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1, iPadreK1=p1}] (initialized) [org.hibernate.engine.internal.Collections] (http-localhost/127.0.0.1:8080-1) Found collection with unloaded owner: [com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1 , iPadreK1=p1 }] [org.hibernate.event.internal.AbstractFlushingEventListener] (http-localhost/127.0.0.1:8080-1) Flushed: 0 insertions, 0 updates, 0 deletions to 4 objects [org.hibernate.event.internal.AbstractFlushingEventListener] (http-localhost/127.0.0.1:8080-1) Flushed: 0 (re)creations, 0 updates, 0 removals to 2 collections [org.hibernate.internal.util.EntityPrinter] (http-localhost/127.0.0.1:8080-1) Listing entities: [org.hibernate.internal.util.EntityPrinter] (http-localhost/127.0.0.1:8080-1) com.dat.abs.run.FiglioBean{iDescrizioneFiglio= , iFiglioPK=component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=1 , iPadrePadreK1=p1 , iFiglioK1=1 , iPadrePadreK2=p1 }, iABSUniqueId=249} [org.hibernate.internal.util.EntityPrinter] (http-localhost/127.0.0.1:8080-1) com.dat.abs.run.ABSOutQueueBean{iCreationDateTime=2012-02-17 07:51:10.0, iLastUpdateUser=null, iCreationUser=system , iLastUpdateDateTime=null, iPrintServiceName=null, iId=component[iName]{iName=#01 }, iDescription=01 } [org.hibernate.internal.util.EntityPrinter] (http-localhost/127.0.0.1:8080-1) com.dat.abs.run.FiglioBean{iDescrizioneFiglio=f1 , iFiglioPK=component[iFiglioK1,iFiglioK2,iPadrePadreK1,iPadrePadreK2]{iFiglioK2=f1 , iPadrePadreK1=p1 , iFiglioK1=f1 , iPadrePadreK2=p1 }, iABSUniqueId=248} [org.hibernate.internal.util.EntityPrinter] (http-localhost/127.0.0.1:8080-1) com.dat.abs.run.PadreBean{iPadrePK=component[iPadreK1,iPadreK2]{iPadreK2=p1, iPadreK1=p1}, iAbsOutQueueBean=com.dat.abs.run.ABSOutQueueBean#component[iName]{iName=#01 }, iDescription=p1 , iABSUniqueId=247, iFiglioBeans=[]} [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) Releasing JDBC connection [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) Aggressively releasing JDBC connection
正如您所看到的,Hibernate首先加载了孩子,但是在清除它之后。 请参阅该行前面附带的日志:找到带有已卸载所有者的集合:消息
问题是DBM用来填充CHARs列的空白区域,我已经说过了,如果我在我的键列中插入所有字符也一样。
那么,是否有一个解决方案让Hibernate的子集合使用CHAR列作为未完全填充的主键?
提前感谢您的时间
答案 0 :(得分:1)
我已经解决了编写自己的用户类型的问题。 我在这里发帖因为可能对其他人有用。 使用db2 9.x和Oracle 12c进行测试
package com.dat.abs.run; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.usertype.UserType; public class ABSChar implements UserType { public int[] sqlTypes() { return new int[] { Types.CHAR, }; } public Class returnedClass() { return String.class; } public boolean equals(Object x, Object y) throws HibernateException { return (x == y) || (x != null && y != null && (x.equals(y))); } public Object deepCopy(Object value) throws HibernateException { if (value == null) return null; return new String((String) value); } public boolean isMutable() { return false; } @Override public int hashCode(Object aValue) throws HibernateException { return aValue.hashCode(); } @Override public Object replace(Object aOriginal, Object aTarget, Object aOwner) throws HibernateException { return aOriginal; } @Override public Object assemble(Serializable aChaced, Object aOwner) throws HibernateException { return aChaced; } @Override public Serializable disassemble(Object aValue) throws HibernateException { return (Serializable) aValue; } @Override public Object nullSafeGet(ResultSet aRs, String[] aNames, SessionImplementor aSession, Object aOwner) throws HibernateException, SQLException { String val = aRs.getString(aNames[0]); if (val == null) { return null; } return val.trim(); } @Override public void nullSafeSet(PreparedStatement aStatament, Object aValue, int aIndex, SessionImplementor aSession) throws HibernateException, SQLException { aStatament.setString(aIndex, (String) aValue); } }
这是使用bean类中的类型
@Type(type = "com.dat.abs.run.ABSChar") @Column(name = "PADREPADREK1", length = 20) private String iPadrePadreK1; @Type(type = "com.dat.abs.run.ABSChar") @Column(name = "PADREPADREK2", length = 20) private String iPadrePadreK2; @Type(type = "com.dat.abs.run.ABSChar") @Column(name = "FIGLIOK1", length = 20) private String iFiglioK1; @Type(type = "com.dat.abs.run.ABSChar") @Column(name = "FIGLIOK2", length = 20)