【发布时间】:2009-10-19 19:48:23
【问题描述】:
注意:由于提供了 cmets,我已更改提供的详细信息。新的技术细节实际上是我目前正在尝试运行的代码。
我的 OneToMany / ManyToOne 双向关系之一目前出现了一个奇怪的问题。
在父表中,我有一个 long 作为标识符,而子表除了另一个字段之外也有该列,它构成了它的复合键。
在我查询的示例数据中,子表中有 1 条父记录和 3 条相关记录。目前,当我使用条件对象查询表时,我得到了 3 个父 (CoPolicyPointer) 记录,其中 2 个没有关联的子 (CoTransactionSummary) 表链接,然后是正确填充的第三个。我本来希望只能得到一个结果,这就是我感到困惑的原因。您知道为什么会发生这种情况吗?
我在下面提供了更多技术数据。
父表 (CoPolicyPointer) 列数据类型 SystemAssignId 字符串(主键) PolicyPrefixCd 字符串 PolicyId 字符串 PolicySeqNo int 子表(CoTransaction 摘要) 列数据类型 SystemAssignId 字符串(复合键) TransSeqId int(复合键) TransType varchar(4)Criteria 语句如下所示:
Criteria criteria = session.createCriteria(classToUse);
criteria.createAlias("coTransactionSummaries", "ts");
criteria.add(Restrictions.ne("ts.transInProcessCd", "VIEW"));
criteria.add(Restrictions.gt("ts.transSeqId", Short.valueOf("0")));
criteria.add(Restrictions.eq(BaseCoPolicyPointer.COL_POLICY_PREFIX_CD,
policyNumber.getPrefix().getLiteral()));
criteria.add(Restrictions.eq(BaseCoPolicyPointer.COL_POLICY_ID,
policyNumber.getId()));
父类看起来像:
@Entity(name = "CoPolicyPointer")
public class CoPolicyPointerRedo {
private static final String CLASS_NAME = CoPolicyPointerRedo.class
.getName();
private static final Logger logger = Logger.getLogger(CLASS_NAME);
private String systemAssignId;
private String policyPrefixCd;
private String policyId;
private String policyNumber;
private Short policySeqNo;
private Set coTransactionSummaries;
@Id
public String getSystemAssignId() {
return systemAssignId;
}
public void setSystemAssignId(String systemAssignId) {
this.systemAssignId = systemAssignId;
}
@Column
public String getPolicyId() {
return policyId;
}
public void setPolicyId(String policyId) {
this.policyId = policyId;
}
@Column
public String getPolicyPrefixCd() {
return policyPrefixCd;
}
public void setPolicyPrefixCd(String policyPrefixCd) {
this.policyPrefixCd = policyPrefixCd;
}
@Column
public Short getPolicySeqNo() {
return policySeqNo;
}
public void setPolicySeqNo(Short policySeqNo) {
this.policySeqNo = policySeqNo;
}
@OneToMany(targetEntity = CoTransactionSummaryRedo.class, mappedBy = "coPolicyPointer")
public Set getCoTransactionSummaries() {
return coTransactionSummaries;
}
public void setCoTransactionSummaries(Set coTransactionSummaries) {
this.coTransactionSummaries = coTransactionSummaries;
}
}
子类看起来像:
@Entity(name = "CoTransactionSummary")
public class CoTransactionSummaryRedo {
private static final String CLASS_NAME = CoTransactionSummaryRedo.class
.getName();
private static final Logger logger = Logger.getLogger(CLASS_NAME);
private String transTypeCd;
private String transInProcessCd;
private CoPolicyPointerRedo coPolicyPointer;
private CoTransactionSummaryIdRedo id;
@EmbeddedId
public CoTransactionSummaryIdRedo getId() {
return id;
}
public void setId(CoTransactionSummaryIdRedo id) {
this.id = id;
}
@Column
public String getTransInProcessCd() {
return transInProcessCd;
}
public void setTransInProcessCd(String transInProcessCd) {
this.transInProcessCd = transInProcessCd;
}
@Column
public String getTransTypeCd() {
return transTypeCd;
}
public void setTransTypeCd(String transTypeCd) {
this.transTypeCd = transTypeCd;
}
@ManyToOne()
@JoinColumn(name = "systemAssignId", insertable = false, updatable = false)
public CoPolicyPointerRedo getCoPolicyPointer() {
return coPolicyPointer;
}
public void setCoPolicyPointer(CoPolicyPointerRedo coPolicyPointer) {
this.coPolicyPointer = coPolicyPointer;
}
}
子类的ID类如下:
@Embeddable
public class CoTransactionSummaryIdRedo implements java.io.Serializable {
private String systemAssignId;
private short transSeqId;
public CoTransactionSummaryIdRedo() {
}
public CoTransactionSummaryIdRedo(String systemAssignId, short transSeqId) {
this.systemAssignId = systemAssignId;
this.transSeqId = transSeqId;
}
@Column
public String getSystemAssignId() {
return systemAssignId;
}
public void setSystemAssignId(String systemAssignId) {
this.systemAssignId = systemAssignId;
}
@Column
public short getTransSeqId() {
return transSeqId;
}
public void setTransSeqId(short transSeqId) {
this.transSeqId = transSeqId;
}
@Override
public boolean equals(Object other) {
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof CoTransactionSummaryIdRedo))
return false;
CoTransactionSummaryIdRedo castOther = (CoTransactionSummaryIdRedo) other;
return ((this.getSystemAssignId() == castOther.getSystemAssignId()) || (this
.getSystemAssignId() != null
&& castOther.getSystemAssignId() != null && this
.getSystemAssignId().equals(castOther.getSystemAssignId())))
&& (this.getTransSeqId() == castOther.getTransSeqId());
}
@Override
public int hashCode() {
int result = 17;
result = 37
* result
+ (getSystemAssignId() == null ? 0 : this.getSystemAssignId()
.hashCode());
result = 37 * result + this.getTransSeqId();
return result;
}
}
我已经打开了 TRACE 的日志记录,这是正在生成的内容。
08:20:47,907 调试 SQL:111 - 选择 this_.systemAssignId 作为 systemAs1_1_2_, this_.policyId 作为 policyId1_2_, this_.policyPrefixCd 作为 policyPr3_1_2_, this_.policySeqNo 作为 policySe4_1_2_, ts1_.systemAssignId 作为 systemAs1_0_0_, ts1_.transSeqId 作为 transSeqId0_如transInP3_0_0_,ts1_.transTypeCd如transTyp4_0_0_,copolicypo4_.systemAssignId如systemAs1_1_1_,copolicypo4_.policyId如policyId1_1_,copolicypo4_.policyPrefixCd如policyPr3_1_1_,copolicypo4_.policySeqNo如policySe4_1_1_从CoPolicyPointer THIS_内部联接上this_.systemAssignId = ts1_.systemAssignId CoTransactionSummary ts1_左外连接CoPolicyPointer copolicypo4_ on ts1_.systemAssignId=copolicypo4_.systemAssignId where this_.policyPrefixCd=?和 this_.policyId=?而 this_.policySeqNo=? 休眠:选择this_.systemAssignId为systemAs1_1_2_,this_.policyId为policyId1_2_,this_.policyPrefixCd为policyPr3_1_2_,this_.policySeqNo为policySe4_1_2_,ts1_.systemAssignId为systemAs1_0_0_,ts1_.transSeqId为transSeqId0_0_,ts1_.transInProcessCd为transInP3_0_0_,ts1_.transTypeCd为transTyp4_0_0_ ,copolicypo4_.systemAssignId如systemAs1_1_1_,copolicypo4_.policyId如policyId1_1_,copolicypo4_.policyPrefixCd如policyPr3_1_1_,copolicypo4_.policySeqNo如policySe4_1_1_从CoPolicyPointer THIS_内部联接上this_.systemAssignId = ts1_.systemAssignId CoTransactionSummary ts1_左外连接CoPolicyPointer copolicypo4_上ts1_.systemAssignId = copolicypo4_ .systemAssignId where this_.policyPrefixCd=?和 this_.policyId=?而 this_.policySeqNo=? 19:14:30,938 调试 AbstractBatcher:513 - 准备语句 19:14:30,969 调试字符串类型:151 - 将“WA”绑定到参数:1 19:14:30,969 调试字符串类型:151 - 将“0100036449”绑定到参数:2 19:14:30,969 DEBUG ShortType:151 - 将“0”绑定到参数:3 19:14:30,969 DEBUG AbstractBatcher:426 - 即将打开 ResultSet(打开 ResultSets:0,全局:0) 19:14:30,969 DEBUG Loader:717 - 处理结果集 19:14:30,969 调试加载器:722 - 结果集行:0 19:14:30,969 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,969 DEBUG ShortType:193 - 返回“0”作为列:transSeqId0_0_ 19:14:30,969 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_1_ 19:14:30,969 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_2_ 19:14:30,969 调试加载器:1197 - 结果行:EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}],EntityKey[CoPolicyPointerRedo#00502000000000],EntityKey[CoPolicyPointer20000005000000000050000000005 19:14:30,969 调试加载程序:1379 - 从 ResultSet 初始化对象:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 19:14:30,969 调试 AbstractEntityPersister:2059 - 水合实体:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 19:14:30,969 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,969 DEBUG StringType:193 - 返回“PCNM”作为列:transInP3_0_0_ 19:14:30,969 DEBUG StringType:193 - 返回“PCNM”作为列:transTyp4_0_0_ 19:14:30,969 调试加载程序:1379 - 从 ResultSet 初始化对象:[CoPolicyPointerRedo#00502000000000] 19:14:30,969 调试 AbstractEntityPersister:2059 - 水合实体:[CoPolicyPointerRedo#00502000000000] 19:14:30,985 DEBUG StringType:193 - 返回 '0100036449' 作为列:policyId1_1_ 19:14:30,985 DEBUG StringType:193 - 返回 'WA' 作为列:policyPr3_1_1_ 19:14:30,985 DEBUG ShortType:193 - 返回 '0' 作为列:policySe4_1_1_ 19:14:30,985 调试加载器:722 - 结果集行:1 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,985 DEBUG ShortType:193 - 返回“1”作为列:transSeqId0_0_ 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_1_ 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_2_ 19:14:30,985 DEBUG Loader:1197 - 结果行:EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}], EntityKey[CoPolicyPointerRedo#00502000000000], EntityKey[CoPolicyPointer20000005000000000050000000005 19:14:30,985 调试加载程序:1379 - 从 ResultSet 初始化对象:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 19:14:30,985 调试 AbstractEntityPersister:2059 - 水合实体:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,985 DEBUG StringType:193 - 返回“PCNM”作为列:transInP3_0_0_ 19:14:30,985 DEBUG StringType:193 - 返回“PCNM”作为列:transTyp4_0_0_ 19:14:30,985 调试加载器:722 - 结果集行:2 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,985 DEBUG ShortType:193 - 返回“5”作为列:transSeqId0_0_ 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_1_ 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_2_ 19:14:30,985 DEBUG Loader:1197 - 结果行:EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}], EntityKey[CoPolicyPointerRedo#00502000000000], EntityKey[CoPolicyPointer20000005000000000050000000005 19:14:30,985 调试加载程序:1379 - 从 ResultSet 初始化对象:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 19:14:30,985 调试 AbstractEntityPersister:2059 - 水合实体:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,985 DEBUG StringType:193 - 返回“PCNM”作为列:transInP3_0_0_ 19:14:30,985 DEBUG StringType:193 - 返回“PCNM”作为列:transTyp4_0_0_ 19:14:30,985 调试加载器:722 - 结果集行:3 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,985 DEBUG ShortType:193 - 返回“6”作为列:transSeqId0_0_ 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_1_ 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_1_2_ 19:14:30,985 DEBUG Loader:1197 - 结果行:EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}],EntityKey[CoPolicyPointerRedo#00502000000000],EntityKey[CoPolicyPointer20000005000000000050000000005 19:14:30,985 调试加载程序:1379 - 从 ResultSet 初始化对象:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 19:14:30,985 调试 AbstractEntityPersister:2059 - 水合实体:[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 19:14:30,985 DEBUG StringType:193 - 返回 '00502000000000' 作为列:systemAs1_0_0_ 19:14:30,985 DEBUG StringType:193 - 返回“PCNM”作为列:transInP3_0_0_ 19:14:30,985 DEBUG StringType:193 - 返回“PCNM”作为列:transTyp4_0_0_ 19:14:30,985 DEBUG Loader:744 - 完成处理结果集(4 行) 19:14:30,985 DEBUG AbstractBatcher:433 - 即将关闭 ResultSet(打开 ResultSets:1,全局:1) 19:14:30,985 DEBUG AbstractBatcher:418 - 即将关闭 PreparedStatement(打开 PreparedStatements:1,全局:1) 19:14:30,985 调试 AbstractBatcher:562 - 结束声明 19:14:30,985 DEBUG ConnectionManager:427 - 积极释放 JDBC 连接 19:14:30,985 DEBUG ConnectionManager:464 - 释放 JDBC 连接 [(打开 PreparedStatements:0,全局:0)(打开 ResultSets:0,全局:0)] 19:14:30,985 DEBUG DriverManagerConnectionProvider:152 - 返回连接到池,池大小:1 19:14:30,985 调试加载器:874 - 水合对象总数:5 19:14:30,985 调试 TwoPhaseLoad:130 - 解析 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 的关联 19:14:30,985 调试 DefaultLoadEventListener:199 - 加载实体:[CoPolicyPointerRedo#00502000000000] 19:14:30,985 DEBUG DefaultLoadEventListener:372 - 尝试解决:[CoPolicyPointerRedo#00502000000000] 19:14:30,985 DEBUG DefaultLoadEventListener:389 - 会话缓存中已解析的对象:[CoPolicyPointerRedo#00502000000000] 19:14:30,985 调试 TwoPhaseLoad:226 - 完成实体化 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 19:14:30,985 调试 TwoPhaseLoad:130 - 解析 [CoPolicyPointerRedo#00502000000000] 的关联 19:14:30,985 DEBUG LoadContexts:218 - 创建集合包装器:[CoPolicyPointerRedo.coTransactionSummaries#00502000000000] 19:14:31,047 调试 TwoPhaseLoad:226 - 完成实体化 [CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 TwoPhaseLoad:130 - 解析 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 的关联 19:14:31,047 调试 DefaultLoadEventListener:199 - 加载实体:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 DefaultLoadEventListener:372 - 尝试解决:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 DefaultLoadEventListener:389 - 会话缓存中已解析的对象:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 TwoPhaseLoad:226 - 完成实体化 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 19:14:31,047 调试 TwoPhaseLoad:130 - 解析 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 的关联 19:14:31,047 调试 DefaultLoadEventListener:199 - 加载实体:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 DefaultLoadEventListener:372 - 尝试解决:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 DefaultLoadEventListener:389 - 会话缓存中已解析的对象:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 TwoPhaseLoad:226 - 完成实体化 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 19:14:31,047 调试 TwoPhaseLoad:130 - 解析 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 的关联 19:14:31,047 调试 DefaultLoadEventListener:199 - 加载实体:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 DefaultLoadEventListener:372 - 尝试解决:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 DefaultLoadEventListener:389 - 会话缓存中已解析的对象:[CoPolicyPointerRedo#00502000000000] 19:14:31,047 调试 TwoPhaseLoad:226 - 完成实体化 [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 19:14:31,047 DEBUG StatefulPersistenceContext:860 - 初始化非惰性集合 19:14:31,047 调试 JDBCContext:260 - 自动提交后 19:14:31,047 DEBUG ConnectionManager:427 - 积极释放 JDBC 连接 19:14:31,047 DEBUG SessionImpl:449 - 事务完成后【问题讨论】:
-
您发布的日志中唯一的查询与提供的条件不匹配。除此之外,使用systemAssignId(这是父母的PK)从孩子到CoPolicyPointerRedo的ManyToOne相当奇怪(为什么它不在父母身上?)我也觉得很奇怪上面的查询对孩子有内部连接并在ManyToOne上加入因为默认情况下两者都应该是惰性的。你在某处覆盖它吗?
-
所以这个问题一直是火车失事......对此感到抱歉。我已将标准数据和生成的 sql 修改为我现在所拥有的。我对您断言 systemAssignId 不在父级上的声明感到困惑,它被标记为 @ID 字段。如果您指的是 @ManyToOne 关系,我使用 mappedBy 属性来指定应该如何完成映射。关于查询的最后一条语句,您是正确的,因为我强制连接发生在条件语句中。
-
请忽略我的评论:systemAssignId - 你的标准与生成的 SQL 让我失望。我已经更新了我的答案,请看一下。