2012-08-24 86 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

不工作是不同的单词,提供您的休眠版本和完整的查询 –