2012-08-24 114 views
5

我想問一下,我有可能創建查詢投影和多個級別的標準? 我有2模型類:複雜的休眠投影

@Entity 
@Table(name = "person") 
public class Person implements Serializable { 
    @Id 
    @GeneratedValue 
    private int personID; 
    private double valueDouble; 
    private int valueInt; 
    private String name; 
    @OneToOne(cascade = {CascadeType.ALL}, orphanRemoval = true) 
    @JoinColumn(name="wifeId") 
    private Wife wife; 
     /* 
     * Setter Getter  
     */ 
} 


@Entity 
@Table(name = "wife") 
public class Wife implements Serializable { 

    @Id 
    @GeneratedValue  
    @Column(name="wifeId") 
    private int id; 
    @Column(name="name") 
    private String name; 
    @Column(name="age") 
    private int age;    
    /* 
    * Setter Getter 
    */  
} 

我的標準API:

ProjectionList projections = Projections.projectionList(); 
projections.add(Projections.property("this.personID"), "personID"); 
projections.add(Projections.property("this.wife"), "wife"); 
projections.add(Projections.property("this.wife.name"), "wife.name"); 

Criteria criteria = null; 
criteria = getHandlerSession().createCriteria(Person.class); 
criteria.createCriteria("wife", "wife", JoinType.LEFT.ordinal()); 
criterion = Restrictions.eq("wife.age", 19); 
criteria.add(criterion); 
criteria.setProjection(projections); 
criteria.setResultTransformer(Transformers.aliasToBean(Person.class)); 
return criteria.list(); 

,我希望,我可以查詢人,與妻子屬性指定的標準,以及指定的返回結果集。 所以我用投影獲得指定的返回結果集

我想personID,名稱(人),姓名(妻子)將返回。我如何使用API​​,我更喜歡使用Hibernate Criteria API。

這一次,我用上面得到我預期的結果代碼,但它會拋出異常與錯誤消息: Exception in thread "main" org.hibernate.QueryException: could not resolve property: wife.name of: maladzan.model.Person, 是否我Restrictions.eq("wife.age", 19);是獲得具有妻子19她的年齡價值的人是否正確?

感謝

回答

6

AFAIK這是不可能的項目深具aliastobean變壓器不止一個級別。你的選擇是

  • 創建一個扁平的數據傳輸對象(DTO)
  • 填補由此造成的人員在記錄自己
  • 實現自己的使用ResultTransformer(類似於選項2)

選項1個長相像這樣:

Criteria criteria = getHandlerSession().createCriteria(Person.class) 
    .createAlias("wife", "wife", JoinType.LEFT.ordinal()) 
    .add(Restrictions.eq("wife.age", 19)); 
    .setProjection(Projections.projectionList() 
     .add(Projections.property("personID"), "personID") 
     .add(Projections.property("name"), "personName") 
     .add(Projections.property("wife.name"), "wifeName")); 
    .setResultTransformer(Transformers.aliasToBean(PersonWifeDto.class)); 

return criteria.list(); 
5

我寫了ResultTransformer,就是這麼做的。它的名字是AliasToBeanNestedResultTransformer,查看​​。

+0

嗨薩米安多尼。我確實使用過你的AliasToBeanNestedResultTransformer創建嵌套對象,我把嵌套對象作爲嵌套對象,但是我有一個小問題。我打算只在嵌套對象中獲得特定字段,在父對象中只有幾個字段,但結果是父對象中的所有字段和嵌套對象中的所有字段作爲嵌套對象。我不知道你的自定義轉換器是否只能獲取特定的字段,是否可以只嵌套對象中的特定字段作爲嵌套對象? –

+0

你有沒有解決這個問題? –

+0

@JatinMalwal有什麼問題? –

1

謝謝薩米安多尼。我能夠對您的AliasToBeanNestedResultTransformer進行小修改以適應我的情況。我發現的是,嵌套變換器不支持字段處於超類的場景,所以我增強了它,以便在您要投影到的類的類繼承層次結構中查找深達10級的字段:

public Object transformTuple(Object[] tuple, String[] aliases) { 

     ... 


       if (alias.contains(".")) { 
        nestedAliases.add(alias); 

        String[] sp = alias.split("\\."); 
        String fieldName = sp[0]; 
        String aliasName = sp[1]; 

        Class<?> subclass = getDeclaredFieldForClassOrSuperClasses(resultClass, fieldName, 1); 
... 
} 

凡getDeclaredFieldForClassOrSuperClasses()被定義如下:

private Class<?> getDeclaredFieldForClassOrSuperClasses(Class<?> resultClass, String fieldName, int level) throws NoSuchFieldException{ 
    Class<?> result = null; 
    try { 
     result = resultClass.getDeclaredField(fieldName).getType(); 
    } catch (NoSuchFieldException e) { 
     if (level <= 10){ 
     return getDeclaredFieldForClassOrSuperClasses(
       resultClass.getSuperclass(), fieldName, level++); 
     } else { 
      throw e; 
     } 
    } 
    return result; 
} 

我的休眠投影此嵌套屬性是這樣的:

Projections.projectionList().add(Property.forName("metadata.copyright").as("productMetadata.copyright")); 

和類我伸入這個樣子的:

public class ProductMetadata extends AbstractMetadata { 
... 
} 

public abstract class AbstractMetadata { 
... 
    protected String copyright; 
... 
} 
+0

您是否編寫過支持'OneToMany(Collections)'的NestedTransformer? –

+0

@Sangdol寫道,我只是增強了它的功能,支持從基類到10個級別的領域投影 – whitestryder

-1

而不是創造Data Transfer Object (DTO)
projectionlist修改下面,它會爲你工作。

ProjectionList projections = Projections.projectionList(); 
    projections.add(Projections.property("person.personID"), "personID"); 
    projections.add(Projections.property("person.wife"), "wife"); 
    projections.add(Projections.property("wife.name")); 

    Criteria criteria = null; 
    criteria = getHandlerSession().createCriteria(Person.class,"person").createAlias("person.wife", "wife"); 
    criterion = Restrictions.eq("wife.age", 19); 
    criteria.add(criterion); 
    criteria.setProjection(projections); 
    criteria.setResultTransformer(Transformers.aliasToBean(Person.class)); 
    return criteria.list(); 
+0

它不適合我。 –

+0

不工作 –

+0

不工作是不同的單詞,提供您的休眠版本和完整的查詢 –