2009-10-19 71 views
1

注意:由于提供的注释,我已更改提供的详细信息。新的技术细节实际上是我试图运行的代码。使用带复合键的Hibernate Criteria对象的问题

我有一个奇怪的问题目前与我的OneToMany/ManyToOne双向关系之一。

在父表中,我有一个很长的标识符,除了构成其组合键的另一个字段外,子标题还包含该列。

在我查询的示例数据中,在子表中有1条父记录和3条相关记录。目前,当我使用条件对象查询表时,我得到3个父(CoPolicyPointer)记录,其中2个没有关联的子(CoTransactionSummary)表链接,然后是三个正确填充。我希望只能得到一个结果,这就是为什么我很困惑。你有什么想法,为什么发生这种情况?

我在下面提供了更多的技术数据。

 
Parent Table (CoPolicyPointer) 
Column   Data Type 
SystemAssignId String    (Primary Key) 
PolicyPrefixCd String 
PolicyId   String 
PolicySeqNo  int 




Child Table (CoTransaction Summary) 
Column   Data Type 
SystemAssignId String     (composite key) 
TransSeqId  int      (composite key) 
TransType varchar(4) 

条件语句如下所示:

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 DEBUG SQL:111 - select this_.systemAssignId as systemAs1_1_2_, this_.policyId as policyId1_2_, this_.policyPrefixCd as policyPr3_1_2_, this_.policySeqNo as policySe4_1_2_, ts1_.systemAssignId as systemAs1_0_0_, ts1_.transSeqId as transSeqId0_0_, ts1_.transInProcessCd as transInP3_0_0_, ts1_.transTypeCd as transTyp4_0_0_, copolicypo4_.systemAssignId as systemAs1_1_1_, copolicypo4_.policyId as policyId1_1_, copolicypo4_.policyPrefixCd as policyPr3_1_1_, copolicypo4_.policySeqNo as policySe4_1_1_ from CoPolicyPointer this_ inner join CoTransactionSummary ts1_ on this_.systemAssignId=ts1_.systemAssignId left outer join CoPolicyPointer copolicypo4_ on ts1_.systemAssignId=copolicypo4_.systemAssignId where this_.policyPrefixCd=? and this_.policyId=? and this_.policySeqNo=? 
Hibernate: select this_.systemAssignId as systemAs1_1_2_, this_.policyId as policyId1_2_, this_.policyPrefixCd as policyPr3_1_2_, this_.policySeqNo as policySe4_1_2_, ts1_.systemAssignId as systemAs1_0_0_, ts1_.transSeqId as transSeqId0_0_, ts1_.transInProcessCd as transInP3_0_0_, ts1_.transTypeCd as transTyp4_0_0_, copolicypo4_.systemAssignId as systemAs1_1_1_, copolicypo4_.policyId as policyId1_1_, copolicypo4_.policyPrefixCd as policyPr3_1_1_, copolicypo4_.policySeqNo as policySe4_1_1_ from CoPolicyPointer this_ inner join CoTransactionSummary ts1_ on this_.systemAssignId=ts1_.systemAssignId left outer join CoPolicyPointer copolicypo4_ on ts1_.systemAssignId=copolicypo4_.systemAssignId where this_.policyPrefixCd=? and this_.policyId=? and this_.policySeqNo=? 
19:14:30,938 DEBUG AbstractBatcher:513 - preparing statement 
19:14:30,969 DEBUG StringType:151 - binding 'WA' to parameter: 1 
19:14:30,969 DEBUG StringType:151 - binding '0100036449' to parameter: 2 
19:14:30,969 DEBUG ShortType:151 - binding '0' to parameter: 3 
19:14:30,969 DEBUG AbstractBatcher:426 - about to open ResultSet (open ResultSets: 0, globally: 0) 
19:14:30,969 DEBUG Loader:717 - processing result set 
19:14:30,969 DEBUG Loader:722 - result set row: 0 
19:14:30,969 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,969 DEBUG ShortType:193 - returning '0' as column: transSeqId0_0_ 
19:14:30,969 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_1_ 
19:14:30,969 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_2_ 
19:14:30,969 DEBUG Loader:1197 - result row: EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}], EntityKey[CoPolicyPointerRedo#00502000000000], EntityKey[CoPolicyPointerRedo#00502000000000] 
19:14:30,969 DEBUG Loader:1379 - Initializing object from ResultSet: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 
19:14:30,969 DEBUG AbstractEntityPersister:2059 - Hydrating entity: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 
19:14:30,969 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,969 DEBUG StringType:193 - returning 'PCNM' as column: transInP3_0_0_ 
19:14:30,969 DEBUG StringType:193 - returning 'PCNM' as column: transTyp4_0_0_ 
19:14:30,969 DEBUG Loader:1379 - Initializing object from ResultSet: [CoPolicyPointerRedo#00502000000000] 
19:14:30,969 DEBUG AbstractEntityPersister:2059 - Hydrating entity: [CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG StringType:193 - returning '0100036449   ' as column: policyId1_1_ 
19:14:30,985 DEBUG StringType:193 - returning 'WA ' as column: policyPr3_1_1_ 
19:14:30,985 DEBUG ShortType:193 - returning '0' as column: policySe4_1_1_ 
19:14:30,985 DEBUG Loader:722 - result set row: 1 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,985 DEBUG ShortType:193 - returning '1' as column: transSeqId0_0_ 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_1_ 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_2_ 
19:14:30,985 DEBUG Loader:1197 - result row: EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}], EntityKey[CoPolicyPointerRedo#00502000000000], EntityKey[CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG Loader:1379 - Initializing object from ResultSet: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG AbstractEntityPersister:2059 - Hydrating entity: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,985 DEBUG StringType:193 - returning 'PCNM' as column: transInP3_0_0_ 
19:14:30,985 DEBUG StringType:193 - returning 'PCNM' as column: transTyp4_0_0_ 
19:14:30,985 DEBUG Loader:722 - result set row: 2 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,985 DEBUG ShortType:193 - returning '5' as column: transSeqId0_0_ 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_1_ 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_2_ 
19:14:30,985 DEBUG Loader:1197 - result row: EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}], EntityKey[CoPolicyPointerRedo#00502000000000], EntityKey[CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG Loader:1379 - Initializing object from ResultSet: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG AbstractEntityPersister:2059 - Hydrating entity: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,985 DEBUG StringType:193 - returning 'PCNM' as column: transInP3_0_0_ 
19:14:30,985 DEBUG StringType:193 - returning 'PCNM' as column: transTyp4_0_0_ 
19:14:30,985 DEBUG Loader:722 - result set row: 3 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,985 DEBUG ShortType:193 - returning '6' as column: transSeqId0_0_ 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_1_ 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_1_2_ 
19:14:30,985 DEBUG Loader:1197 - result row: EntityKey[CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}], EntityKey[CoPolicyPointerRedo#00502000000000], EntityKey[CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG Loader:1379 - Initializing object from ResultSet: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG AbstractEntityPersister:2059 - Hydrating entity: [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG StringType:193 - returning '00502000000000' as column: systemAs1_0_0_ 
19:14:30,985 DEBUG StringType:193 - returning 'PCNM' as column: transInP3_0_0_ 
19:14:30,985 DEBUG StringType:193 - returning 'PCNM' as column: transTyp4_0_0_ 
19:14:30,985 DEBUG Loader:744 - done processing result set (4 rows) 
19:14:30,985 DEBUG AbstractBatcher:433 - about to close ResultSet (open ResultSets: 1, globally: 1) 
19:14:30,985 DEBUG AbstractBatcher:418 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1) 
19:14:30,985 DEBUG AbstractBatcher:562 - closing statement 
19:14:30,985 DEBUG ConnectionManager:427 - aggressively releasing JDBC connection 
19:14:30,985 DEBUG ConnectionManager:464 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
19:14:30,985 DEBUG DriverManagerConnectionProvider:152 - returning connection to pool, pool size: 1 
19:14:30,985 DEBUG Loader:874 - total objects hydrated: 5 
19:14:30,985 DEBUG TwoPhaseLoad:130 - resolving associations for [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG DefaultLoadEventListener:199 - loading entity: [CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG DefaultLoadEventListener:372 - attempting to resolve: [CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG DefaultLoadEventListener:389 - resolved object in session cache: [CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG TwoPhaseLoad:226 - done materializing entity [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=0, systemAssignId=00502000000000}] 
19:14:30,985 DEBUG TwoPhaseLoad:130 - resolving associations for [CoPolicyPointerRedo#00502000000000] 
19:14:30,985 DEBUG LoadContexts:218 - creating collection wrapper:[CoPolicyPointerRedo.coTransactionSummaries#00502000000000] 
19:14:31,047 DEBUG TwoPhaseLoad:226 - done materializing entity [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG TwoPhaseLoad:130 - resolving associations for [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 
19:14:31,047 DEBUG DefaultLoadEventListener:199 - loading entity: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG DefaultLoadEventListener:372 - attempting to resolve: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG DefaultLoadEventListener:389 - resolved object in session cache: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG TwoPhaseLoad:226 - done materializing entity [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=1, systemAssignId=00502000000000}] 
19:14:31,047 DEBUG TwoPhaseLoad:130 - resolving associations for [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 
19:14:31,047 DEBUG DefaultLoadEventListener:199 - loading entity: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG DefaultLoadEventListener:372 - attempting to resolve: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG DefaultLoadEventListener:389 - resolved object in session cache: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG TwoPhaseLoad:226 - done materializing entity [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=5, systemAssignId=00502000000000}] 
19:14:31,047 DEBUG TwoPhaseLoad:130 - resolving associations for [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 
19:14:31,047 DEBUG DefaultLoadEventListener:199 - loading entity: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG DefaultLoadEventListener:372 - attempting to resolve: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG DefaultLoadEventListener:389 - resolved object in session cache: [CoPolicyPointerRedo#00502000000000] 
19:14:31,047 DEBUG TwoPhaseLoad:226 - done materializing entity [CoTransactionSummaryRedo#component[systemAssignId,transSeqId]{transSeqId=6, systemAssignId=00502000000000}] 
19:14:31,047 DEBUG StatefulPersistenceContext:860 - initializing non-lazy collections 
19:14:31,047 DEBUG JDBCContext:260 - after autocommit 
19:14:31,047 DEBUG ConnectionManager:427 - aggressively releasing JDBC connection 
19:14:31,047 DEBUG SessionImpl:449 - after transaction completion 
+0

您发布的日志中的唯一查询与提供的条件不符。除此之外,从孩子到CoPolicyPointerRedo的ManyToOne使用systemAssignId(这是父母的PK)是相当奇怪的(为什么不是父母?)我还发现上面的查询具有内部联接子并且加入ManyToOne因为默认情况下两者都应该是懒惰的。你是否在压倒某个地方? – ChssPly76 2009-10-20 02:20:30

+0

所以这个问题一直是火车残骸......对此抱歉。我已经修改了标准数据和生成的sql,这是我现在所拥有的。 我对你的声明感到困惑,声明systemAssignId不在父级上,它被标记为@ID字段。如果您引用@ManyToOne关系,则使用mappedBy属性来指定如何完成映射。在回应关于查询的最后一个陈述时,您是正确的,因为我强制在条件语句内发生连接。 – jwmajors81 2009-10-20 13:28:13

+0

不要忽视我的评论re:systemAssignId - 你的标准vs生成的SQL让我失望。我已经更新了我的答案,请看看。 – ChssPly76 2009-10-21 02:41:07

回答

0

你张贴的映射和您提供的互相冲突的描述:

  1. 映射的逆相关连接列非插入/更新是行不通的。该专栏将如何更新(以及您的父母 - 子女关联是否保持)?
  2. 您的子映射将Child's PK定义为childId(使用@Id注释)。这不是如何映射组合键的; Hibernate会认为childId是一个简单的主键。
  3. 您的条件与您的映射(ParentTable vs Parent等等)不匹配,这可能是一个转换工件,但其他则看起来不错。

我会使用别名,尽管:

Criteria criteria = session.createCriteria(Parent.class) 
.add(Restrictions.eq("policyNo", "1234")) 
.createAlias("child", "children") 
.add(Restrictions.ne("children.transType", "VIEW")); 

更新(基于标准/生成的SQL):

看看由Hibernate生成的SQL根据您的标准(为可读性而缩短):

SELECT this_.*, ts1_.*, copolicypo4_.* 
    FROM CoPolicyPointer this_ 
INNER JOIN CoTransactionSummary ts1_ ON this_.systemAssignId=ts1_.systemAssignId 
    LEFT JOIN CoPolicyPointer copolicypo4_ ON ts1_.systemAssignId=copolicypo4_.systemAssignId 

您会注意到您的“父”表(CoPolicyPointer)加入两次即使您的条件只加入“子女”表。这是因为你在@Entity注释指定实体的名称,但创建一个使用类名的标准,使休眠觉得你连接三个独立的实体:

  1. 标准基于CoPolicyPointerRedo.class
  2. 它加入到CoTransactionSummaryRedo.class其实体名称为CoTransactionSummary
  3. 它连接回CoPolicyPointerRedo.class为``CoPolicyPointer using @ ManyToOne`

您需要与命名保持一致。可以从@Entity声明中删除name声明(您可以使用@Table代替指定表名称),也可以使用session.createCriteria(String entityName)方法创建条件,该方法将实体名称而不是类名称作为参数。

+0

我已经按照建议从注释中移除了insertable = false和updatable = false。 关于你的第二点,你是正确的@ID注释是不正确的,我的代码实际上有@EmbeddedId。我不得不建立一个独立的例子,因为我不应该在互联网上分享公司代码,也没有意识到我使用了错误的注释。对困惑感到抱歉。 我将条件代码更改为上面的代码,并且仍然返回3个父对象,而不是仅附加了子记录的1个对象。 有没有其他想法? – jwmajors81 2009-10-19 21:14:15

+0

我同情“不共享代码”,但我不认为只发布相关片段(以及像您一样更改实体名称)会令人反感 - 否则很难在没有看到确切问题的情况下提出解决方案。 @EmbeddedId你提到应该(是)应用于另一个(组件)类。如何分配该组合ID的cihld的一部分?你在Hibernate中启用了SQL输出吗?如果是这样,生成什么查询?根据你的数据看起来是否合理,或者你看到明显的错误? – ChssPly76 2009-10-19 21:21:22

+0

我试过你的建议,但我仍然得到一个额外的左外连接到SQL的末尾。通过将以下内容添加到标准声明中,我可以得到明显的结果: 条件\t \t \t \t .setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE); 但是,这并不是想法,因为所有记录都从数据库中返回,并且hibernate必须确定要使用哪条记录,所以我仍然希望找到另一个选项。 – jwmajors81 2009-10-22 23:18:08