如何获得B集合中只有少数属性的单个A对象?
我正在制作一个遗留项目,人们有明智的想法将每个关系映射为EAGER。
现在,我们遇到了性能问题。
例如,我有A类,它有一个B对象列表。该列表已在hibernate中映射为一个包,并且懒得加载(到目前为止,这么好)。问题是,B急切地加载了整个怪异的字母:
A.hbm.xml
<hibernate-mapping>
<class="A" table="a" lazy="false">
// properties
<bag name="listOfBs" inverse="true">
<key column="a_id" [...]>
<one-to-many class="B" />
</bag>
</hibernate-mapping>
B.hbm.xml
<hibernate-mapping>
<class="B" table="b" lazy="false">
<many-to-one name="a" class="A" column="a_id" />
// lots of other many-to-one mappings
// properties
// lots of one-to-many properties
</hibernate-mapping>
所以我只需要B的4个属性,但它会获取每个相关对象!
为了解决这个问题而不破坏所有内容,我试图使用hql查询只选择集合中的几列:
"select a, b.field1, b.field2, b.field3, b.field4
from A a inner join B b where a.id = :id"
但我需要一个唯一结果,因此以下查询会导致异常。
答案 0 :(得分:1)
将上述SQL转换为条件后,可以设置结果转换器。在这种情况下,AliasToBeanConstructorResultTransformer可以工作
首先创建一个类来包含条件
中的结果列public class ResultPresenter{
private String a;
private String bField1;
private Integer bField2;
private String bField3;
private String bField4;
public ResultPresenter(String a, String bField1, Integer bField2, String bField3, String bField4){
this.a = a;
this.bField1 = bField1;
this.bField2 = bField2;
this.bField3 = bField3;
this.bField4 = bField4;
}
}
设置所需列的投影,
ProjectionList projectionList = Projections.projectionList();
createProjectionList.add(projections.property(a));
createProjectionList.add(projections.property(b.field1));
createProjectionList.add(projections.property(b.field2));
createProjectionList.add(projections.property(b.field3));
createProjectionList.add(projections.property(b.field4));
将AliasToBeanConstructorResultTransformer设置为条件
java.lang.reflect.Constructor cons = ResultPresenter.class.getConstructor(Arrays.asList(new Class[]{String.class, String.class, Integer.class, String.class, String.class}));
criteria.setResultTransformer(new AliasToBeanConstructorResultTransformer(cons));
答案 1 :(得分:0)
我能够使用两个查询实现我需要的功能。一个用于获取对象A,另一个用于填充B对象列表。我想可以使用两个标准和预测来做同样的事情。
首先,我在B类中创建了一个新的构造函数:
class B {
public B(String field1, String field2, String field3, String field4) {
this.field1 = field1;
this.field2 = field2;
this.field3 = field3;
this.field4 = field4;
}
}
然后,我创建了查询:
public A fetch(Integer id) {
// try-catch abstracted
Query query = getSession.createQuery("from A a where a.id = :id");
query.setParameter("id", id);
A a = (A) query.uniqueResult();
query = getSession().createQuery("select new B(b.field1, b.field2, b.field3, b.field4) from B where b.A.id = :id");
query.setParameter("id", id);
List<B> bs = query.list();
a.setListOfBs(bs);
return a;
}
答案 2 :(得分:-1)
请在hbm的set标签中提及order-by。
<set name="subCompanies" lazy="false" order-by="lower(companyName)">
------------------------------
------------------------------
</set>