【问题标题】:Hibernate one to many unidirectional relation using multiple columns of sql type CHAR使用多个 sql 类型 CHAR 列休眠一对多单向关系
【发布时间】:2014-02-22 17:56:33
【问题描述】:

我有两个名为“Padre”和“Figlio”的实体 Padre 是所有者,Figlio 是孩子 Padre的主键有两列,PADREK1和PADREK2,都是CHAR(20) Figlio 的主键有四列: PADREPADREK1(外国)CHAR(20) PADREPADREK2(外国)CHAR(20) FIGLIOK1 字符 (20) FIGLIOK2 CHAR(20)

这是我的实体类的代码

公共类 PadreBean 扩展 BaseEntityBean3 实现 Serializable { @EmbeddedId PadrePK iPadrePK; @Column(name = "描述") 私有字符串 iDescription; @Column(name = "ABSUNIQUEID") 私人长 iABSUniqueId; @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinColumns( { @JoinColumn(name = "ABSOUTQUEUENAME", nullable = true) }) 私有 ABSOutQueueBean iAbsOutQueueBean; @OneToMany(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "PADREPADREK1", referencedColumnName = "PADREK1"), @JoinColumn(name = "PADREPADREK2", referencedColumnName = "PADREK2") }) 列出 iFiglioBeans; ……

iFiglioBeans 是孩子的集合

问题是: 如果 Padre 的两个主键列都使用全部 20 个字符填充,则一切正常; id padre 的主键列未完全填充 Hibernate 会加载集合 但加载后会清除其内容。

我已激活 Hibernate 日志记录,当我的代码访问子集合时,我看到:

[org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) 获取JDBC连接 [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) 获得JDBC连接 [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) 结果集包含(可能为空)集合:[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) 结果集行:0 [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) 结果行: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) 找到集合行:[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) 结果集行:1 [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) 结果行: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) 找到集合行:[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) 解析 [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) 完成实体化 [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) 解析 [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) 完成实体化 [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 个集合:com.dat.abs.run.PadreBean.iFiglioBeans [org.hibernate.engine.loading.internal.CollectionLoadContext] (http-localhost/127.0.0.1:8080-1) 集合完全初始化:[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) 集合完全初始化:[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 个集合:com.dat.abs.run.PadreBean.iFiglioBeans [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) 释放JDBC连接 [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) 释放JDBC连接 [org.hibernate.loader.Loader] (http-localhost/127.0.0.1:8080-1) 完成加载集合 [org.hibernate.event.internal.AbstractFlushingEventListener] (http-localhost/127.0.0.1:8080-1) 处理刷新时间级联 [org.hibernate.event.internal.AbstractFlushingEventListener] (http-localhost/127.0.0.1:8080-1) 脏检查集合 [org.hibernate.engine.internal.Collections] (http-localhost/127.0.0.1:8080-1) 找到集合:[com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1 , iPadreK1=p1}],是:[com.dat.abs.run.PadreBean.iFiglioBeans#component[iPadreK1,iPadreK2]{iPadreK2=p1, iPadreK1=p1}] (初始化) [org.hibernate.engine.internal.Collections] (http-localhost/127.0.0.1:8080-1) 找到所有者未加载的集合:[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) 刷新:0 次插入,0 次更新,0 次删除到 4 个对象 [org.hibernate.event.internal.AbstractFlushingEventListener] (http-localhost/127.0.0.1:8080-1) Flushed: 0 (re)creations, 0 updates, 0 removes to 2 collections [org.hibernate.internal.util.EntityPrinter] (http-localhost/127.0.0.1:8080-1) 列出实体: [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=组件[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) 释放JDBC连接 [org.hibernate.engine.jdbc.internal.LogicalConnectionImpl] (http-localhost/127.0.0.1:8080-1) 积极释放JDBC连接

正如您所见,Hibernate 首先加载孩子,但在清理之后。 请参阅附加在行前的日志: 找到未加载所有者的集合: 消息

问题是 DBM 用来填充 CHARs 列的空格,我已经说过,如果我在我的键列中插入所有字符都可以正常工作。

那么,是否有解决方案让 Hibernate 使用 CHAR 列作为未完全填充的主键来收集我的孩子?

提前感谢您的宝贵时间

【问题讨论】:

    标签: hibernate jpa


    【解决方案1】:

    我已经解决了编写自己的用户类型的问题。 我在这里发帖是因为可能对其他人有用。 使用 db2 9.x 和 Oracle 12c 进行测试

    包 com.dat.abs.run; 导入 java.io.Serializable; 导入 java.sql.PreparedStatement; 导入java.sql.ResultSet; 导入java.sql.SQLException; 导入 java.sql.Types; 导入 org.hibernate.HibernateException; 导入 org.hibernate.engine.spi.SessionImplementor; 导入 org.hibernate.usertype.UserType; 公共类 ABSChar 实现 UserType { 公共 int[] sqlTypes() { 返回新的 int[] { 类型.CHAR, }; } 公共类返回类() { 返回字符串.class; } 公共布尔等于(对象 x,对象 y)抛出 HibernateException { 返回 (x == y) || (x != null && y != null && (x.equals(y))); } 公共对象 deepCopy(对象值)抛出 HibernateException { 如果(值 == 空) 返回空值; 返回新字符串((字符串)值); } 公共布尔 isMutable() { 返回假; } @覆盖 公共 int hashCode(Object aValue) 抛出 HibernateException { 返回一个Value.hashCode(); } @覆盖 公共对象替换(对象 aOriginal,对象 aTarget,对象 aOwner)抛出 HibernateException { 返回一个Original; } @覆盖 公共对象组装(可序列化 aChaced,对象 aOwner)抛出 HibernateException { 返回一个Chaced; } @覆盖 公共可序列化反汇编(对象 aValue)抛出 HibernateException { 返回(可序列化)aValue; } @覆盖 public Object nullSafeGet(ResultSet aRs, String[] aNames, SessionImplementor aSession, Object aOwner) 抛出 HibernateException, SQLException { 字符串 val = aRs.getString(aNames[0]); 如果(val == null) { 返回空值; } 返回 val.trim(); } @覆盖 公共无效nullSafeSet(PreparedStatement aStatament,对象aValue,int aIndex,SessionImplementor aSession)抛出HibernateException,SQLException { aStatament.setString(aIndex, (String) aValue); } }

    这是使用 bean 类中的类型

    @Type(type = "com.dat.abs.run.ABSChar") @Column(名称=“PADREPADREK1”,长度= 20) 私有字符串 iPadrePadreK1; @Type(type = "com.dat.abs.run.ABSChar") @Column(名称=“PADREPADREK2”,长度= 20) 私有字符串 iPadrePadreK2; @Type(type = "com.dat.abs.run.ABSChar") @Column(名称=“FIGLIOK1”,长度= 20) 私有字符串 iFiglioK1; @Type(type = "com.dat.abs.run.ABSChar") @Column(名称=“FIGLIOK2”,长度= 20)

    【讨论】:

      猜你喜欢
      • 2015-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-22
      • 2023-03-17
      相关资源
      最近更新 更多