Java 复杂冬眠投射
我想问,我是否有可能为多个级别创建查询投影和条件? 我有两个模型课:Java 复杂冬眠投射,java,hibernate,criteria,Java,Hibernate,Criteria,我想问,我是否有可能为多个级别创建查询投影和条件? 我有两个模型课: @Entity @Table(name = "person") public class Person implements Serializable { @Id @GeneratedValue private int personID; private double valueDouble; private int valueInt; private String na
@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();
我希望,我可以用指定的妻子属性条件和指定的返回结果集查询Person。
所以我使用投影来获取指定的返回结果集
我要personID,姓名(个人),姓名(妻子)将返回。我必须如何使用API,我更喜欢使用Hibernate标准API
这一次,我使用了上面的代码来获得预期结果,但它将抛出异常并显示错误消息:
线程“main”org.hibernate.QueryException中的异常:无法解析属性:fixer.name of:maladzan.model.Person
,
以及我的限制.eq(“妻子年龄”,19岁)代码>将妻子年龄为19岁的人作为其年龄值是否正确
感谢您,使用aliastobean transformer无法投射超过一层的深度。你的选择是
- 创建展平数据传输对象(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();
Projections.projectionList().add( Property.forName("metadata.copyright").as("productMetadata.copyright"));
public class ProductMetadata extends AbstractMetadata {
...
}
public abstract class AbstractMetadata {
...
protected String copyright;
...
}
我编写了ResultTransformer
,正是它做到了这一点。它的名字是别名为beannestedResultTransformer
,请查看。谢谢Sami Andoni。我可以使用您的别名BeanNestedResultTransformer,只需稍作修改即可满足我的情况。我发现嵌套的transformer不支持字段位于超类中的场景,因此我对其进行了增强,以便在要投影到的类的类继承层次结构中查找最多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);
...
}
我要投进的班级是这样的:
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();
Projections.projectionList().add( Property.forName("metadata.copyright").as("productMetadata.copyright"));
public class ProductMetadata extends AbstractMetadata {
...
}
public abstract class AbstractMetadata {
...
protected String copyright;
...
}
而不是创建数据传输对象(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();
嗨,萨米·安多尼。我确实使用了您的别名BeanNestedResultTransformer来创建嵌套对象,我确实得到了嵌套对象作为嵌套对象,但我有一个小问题。我打算在嵌套对象中只获取特定字段,在父对象中只获取少数字段,但结果是父对象中的所有字段和嵌套对象中的所有字段都作为嵌套对象。我不知道您的自定义转换器是否能够只提取特定字段,是否可以只提取嵌套对象中的特定字段作为嵌套对象?您解决了这个问题吗?@JatinMalwal什么问题?我正在尝试使用AliasToBeanNestedResultTransformer做同样的事情,只提取特定字段。但是当我尝试这样做时,没有找到AliasedTupleSubstreSultTransformer。您是否编写了一个嵌套的Transformer,它可以支持
OneToMany(Collections)
?@Sangdol编写了它,我只是对它进行了增强,以支持从基类到10个级别的字段的投影深度不工作是另一个词,提供您的hibernate版本和完整查询