我想在Hibernate投影列表中获取嵌套对象值。我有Pojo“费用”和“关税”等级,有一对一和多对一的关系。
我的示例代码如下:
要价
private String id;
private Tariff tariff;
private String name;
@OneToMany(cascade= {CascadeType.ALL},fetch=FetchType.EAGER,mappedBy="charge")
public Tariff getTariff() {
return tariff;
}
public void setTariff(Tariff tariff) {
this.tariff = tariff;
}
关税
private String id;
private String amount;
private Charge charge;
@ManyToOne(cascade={CascadeType.PERSIST},fetch=FetchType.EAGER)
@JoinColumn(name="charge_id")
public Charge getCharge() {
return charge;
}
public void setCharge(Charge charge) {
this.charge = charge;
}
我想按收费模式从关税中提取金额值。
我编写的sql标准在ie中起作用。
选择tariff.amount,charge.name费用,关税charge.name喜欢's%';
我尝试了以下标准。
Criteria cr = getSession().createCriteria(Charge.class,"charge")
.createAlias("charge.tariff","tariff")
.setProjection(Projections.projectionList()
.add(Projections.property("chargeName"),"chargeName")
.add(Projections.property("id"),"id")
.add(Projections.property("tariff.amount"),"amount"))
.add(Restrictions.like("chargeName", name+"%"))
.setResultTransformer(Transformers.aliasToBean(Charge.class));
return cr.list();
我只是检查与restClient它返回空值。如何编写这个sql查询的标准?
我经历过这种要求。我试图使用Transformers.aliasToBean
将嵌套对象作为嵌套对象,但这不起作用。默认情况下,Transformers.aliasToBean
没有能力选择嵌套对象作为嵌套对象。
你可以看看我的问题
使用Projecions从子表中获取特定列
要将嵌套对象作为嵌套对象获取,您需要一个能够这样做的自定义转换器。
这里有一个由samiandoni编写的自定义转换器
https://github.com/samiandoni/AliasToBeanNestedResultTransformer
从该链接中提供的自述
class Person {
private Long id;
private String name;
private Car car;
// getters and setters
}
class Car {
private Long id;
private String color;
// getters and setters
}
List<Person> getPeople() {
ProjectionList projections = Projections.projectionList()
.add(Projections.id().as("id"))
.add(Projections.property("name").as("name"))
.add(Projections.property("c.id").as("car.id"))
.add(Projections.property("c.color").as("car.color"));
Criteria criteria = getCurrentSession().createCriteria(Person.class)
.createAlias("car", "c")
.setProjection(projections)
.setResultTransformer(new AliasToBeanNestedResultTransformer(Person.class));
return (List<Person>) criteria.list();
}
// each car of Person will be populated
上面的转换器能够获取第一级嵌套对象作为嵌套对象,它不支持进一步的深层嵌套对象。因此,经过一些挖掘,我发现了另一个自定义转换器,它能够获取作为嵌套对象的深层嵌套对象
注:
作者:Miguel Resendiz
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.property.Setter;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.transform.AliasedTupleSubsetResultTransformer;
import org.hibernate.transform.ResultTransformer;
/**
* Help to transform alises with nested alises
*
* @author Miguel Resendiz
*
*/
public class AliasToBeanNestedResultTransformer extends
AliasedTupleSubsetResultTransformer {
private static final long serialVersionUID = -8047276133980128266L;
private static final int TUPE_INDEX = 0;
private static final int ALISES_INDEX = 1;
private static final int FIELDNAME_INDEX = 2;
private static final PropertyAccessor accessor = PropertyAccessorFactory
.getPropertyAccessor("property");
private final Class<?> resultClass;
private Object[] entityTuples;
private String[] entityAliases;
private Map<String, Class<?>> fieldToClass = new HashMap<String, Class<?>>();
private Map<String, List<?>> subEntities = new HashMap<String, List<?>>();
private List<String> nestedAliases = new ArrayList<String>();
private Map<String, Class<?>> listFields = new HashMap<String, Class<?>>();
public boolean isTransformedValueATupleElement(String[] aliases,
int tupleLength) {
return false;
}
public AliasToBeanNestedResultTransformer(Class<?> resultClass) {
this.resultClass = resultClass;
}
public Object transformTuple(Object[] tuple, String[] aliases) {
handleSubEntities(tuple, aliases);
cleanParams(tuple, aliases);
ResultTransformer rootTransformer = new AliasToBeanResultTransformer(
resultClass);
Object root = rootTransformer.transformTuple(entityTuples,
entityAliases);
loadSubEntities(root);
cleanMaps();
return root;
}
private void handleSubEntities(Object[] tuple, String[] aliases)
throws HibernateException {
String fieldName = "";
String aliasName = "";
try {
for (int i = 0; i < aliases.length; i++) {
String alias = aliases[i];
if (alias.contains(".")) {
String[] sp = alias.split("\\.");
StringBuilder aliasBuilder = new StringBuilder();
for (int j = 0; j < sp.length; j++) {
if (j == 0) {
fieldName = sp[j];
} else {
aliasBuilder.append(sp[j]);
aliasBuilder.append(".");
}
}
aliasName = aliasBuilder.substring(0,
aliasBuilder.length() - 1);
nestedAliases.add(alias);
manageEntities(fieldName, aliasName, tuple[i]);
}
}
} catch (NoSuchFieldException e) {
throw new HibernateException("Could not instantiate resultclass: "
+ resultClass.getName() + " for field name: " + fieldName
+ " and alias name:" + aliasName);
}
}
private Class<?> findClass(String fieldName) throws NoSuchFieldException,
SecurityException {
if (fieldToClass.containsKey(fieldName)) {
return fieldToClass.get(fieldName);
} else {
Class<?> subclass = resultClass.getDeclaredField(fieldName)
.getType();
if (subclass.equals(List.class) || subclass.equals(Set.class)) {
if (subclass.equals(List.class)) {
listFields.put(fieldName, LinkedList.class);
} else {
listFields.put(fieldName, HashSet.class);
}
Field field = resultClass.getDeclaredField(fieldName);
ParameterizedType genericType = (ParameterizedType) field
.getGenericType();
subclass = (Class<?>) genericType.getActualTypeArguments()[0];
}
fieldToClass.put(fieldName, subclass);
return subclass;
}
}
@SuppressWarnings("unchecked")
private void manageEntities(String fieldName, String aliasName,
Object tupleValue) throws NoSuchFieldException, SecurityException {
Class<?> subclass = findClass(fieldName);
if (!subEntities.containsKey(fieldName)) {
List<Object> list = new ArrayList<Object>();
list.add(new ArrayList<Object>());
list.add(new ArrayList<String>());
list.add(FIELDNAME_INDEX, subclass);
subEntities.put(fieldName, list);
}
((List<Object>) subEntities.get(fieldName).get(TUPE_INDEX))
.add(tupleValue);
((List<String>) subEntities.get(fieldName).get(ALISES_INDEX))
.add(aliasName);
}
private void cleanParams(Object[] tuple, String[] aliases) {
entityTuples = new Object[aliases.length - nestedAliases.size()];
entityAliases = new String[aliases.length - nestedAliases.size()];
for (int j = 0, i = 0; j < aliases.length; j++) {
if (!nestedAliases.contains(aliases[j])) {
entityTuples[i] = tuple[j];
entityAliases[i] = aliases[j];
++i;
}
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void loadSubEntities(Object root) throws HibernateException {
try {
for (String fieldName : subEntities.keySet()) {
Class<?> subclass = (Class<?>) subEntities.get(fieldName).get(
FIELDNAME_INDEX);
ResultTransformer subclassTransformer = new AliasToBeanNestedResultTransformer(
subclass);
Object subObject = subclassTransformer.transformTuple(
((List<Object>) subEntities.get(fieldName).get(0))
.toArray(),
((List<Object>) subEntities.get(fieldName).get(1))
.toArray(new String[0]));
Setter setter = accessor.getSetter(resultClass, fieldName);
if (listFields.containsKey(fieldName)) {
Class<?> collectionClass = listFields.get(fieldName);
Collection subObjectList = (Collection) collectionClass
.newInstance();
subObjectList.add(subObject);
setter.set(root, subObjectList, null);
} else {
setter.set(root, subObject, null);
}
}
} catch (Exception e) {
throw new HibernateException(e);
}
}
private void cleanMaps() {
fieldToClass = new HashMap<String, Class<?>>();
subEntities = new HashMap<String, List<?>>();
nestedAliases = new ArrayList<String>();
listFields = new HashMap<String, Class<?>>();
}
}
只要用上述变压器更换samiandoni的变压器即可。它能够获取更多的深层嵌套对象作为各自的对象。
问题内容: 我想在Hibernate Projection List中使用嵌套对象值。我有OneToMany和ManyToOne关系的Pojo“ Charge”和“ Tariff”课程。 我的示例代码如下: 收费 关税 我想按收费模式从关税中提取金额值。 我写的SQL标准,即工作。 选择charge.amount,charge.name从charge,tariff那里的charge.name喜欢’
嗨,我想写一个查询使用条件:以下查询必须使用条件创建: “从S2中选择不同的(s2Taxper),其中s2Tc='601'和s2Txcd!=”” 提前谢谢
我有一个名为Student实体,它有几个与Student相关的字段,还有一个具有一个任何关系的主题列表。在这里,我需要得到所有的字段,包括主题列表,除了“图像”,因为它使用更多的内存,它需要很长的时间来检索所有行。有没有人可以说,如何创建投影和标准,以检索这个学生对象,没有图像字段单独?有没有像“AliastObeAnneStedResultTransformer”这样的自定义结果转换器?因为在我
我有一个关于嵌套列表投影界面用法的问题。我有两个实体(父和子)(它们有单向关联) 父级=> 子=> 我有两个选择特定列投影界面。 这个查询可以工作,但是它选择ChildEntity的所有列,并且只将id、name propeties映射到ChildProjection。(生成的查询选择所有列,但我想只选择id和name列) 我如何只选择id和name列(为嵌套列表投影界面选择特定列)并映射到Chi
我用的是Java 8号。我有一份汽车物品清单。我想按特定的顺序对它们进行排序。 每个汽车对象都属于一个模型。我喜欢按型号对汽车对象列表进行排序。排序后的列表应该是按照以下顺序,有车型的轿车SEDAN,然后是宝马,然后是独角兽。 所以当我打印排序后的列表时,它应该是这样的 如何使用自定义比较器在模型枚举上实现这种排序顺序。 如果你能帮忙,我很感激
我有带有嵌套文档注释的帖子集合。简单的文档模式如下所示: 我只想投射所要求的评论。我找到了一个可以接受的解决方案。(也只欢迎使用注释对象返回解决方案) 然后我尝试将其应用于带有查询注释的mongoDB存储库接口。 但我得到了演员特例。有没有更好的方法来使用spring data mongodb实现这一点?