Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何编写Hibernate条件以按投影列表获取嵌套对象?_Java_Spring_Hibernate_Criteria_Hibernate Criteria - Fatal编程技术网

Java 如何编写Hibernate条件以按投影列表获取嵌套对象?

Java 如何编写Hibernate条件以按投影列表获取嵌套对象?,java,spring,hibernate,criteria,hibernate-criteria,Java,Spring,Hibernate,Criteria,Hibernate Criteria,我想在Hibernate投影列表中获取嵌套对象值。我有Pojo“费用”和“关税”等级,有一对一和多对一的关系 我的示例代码如下所示: 充电 private String id; private Tariff tariff; private String name; @OneToMany(cascade= {CascadeType.ALL},fetch=FetchType.EAGER,mappedBy="charge") public Tariff getTari

我想在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中起作用

从费用中选择关税、金额、费用、名称 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
无法选择嵌套对象作为嵌套对象

你可以看看我的问题

要将嵌套对象作为嵌套对象获取,您需要一个能够这样做的自定义转换器

这里有一个由samiandoni编写的自定义转换器

从该链接中提供的自述

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

只要用上述变压器更换samiandoni的变压器即可。它能够获取更多的深层嵌套对象作为各自的对象。

AliasToBeanNestedResultTransformer不处理多级嵌套DTO。也就是说,您将无法在其各自的DTO中执行company.employee.location

下面是我编写的一个转换器,它处理多级嵌套DTO。您可以通过以下方式使用它:

criteria.setResultTransformer( 别名为NestedMultilevelResultTransformer(映射Bean))

希望能有帮助

public class AliasToBeanNestedMultiLevelResultTransformer extends AliasedTupleSubsetResultTransformer {

private static final long serialVersionUID = -8047276133980128266L;

public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
    return false;
}

private boolean initialized;
private Class<?> resultClass;
private Map<String,Class<?>> clazzMap = new HashMap<>();
private Map<String,Setter> settersMap = new HashMap<>();

public AliasToBeanNestedMultiLevelResultTransformer(Class<?> resultClass) {
    this.resultClass = resultClass;
}

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

    Map<String,Object> nestedObjectsMap = new HashMap<>();

    Object result;
    try {
        result = resultClass.newInstance();

        if (!initialized){
            initialized = true;
            initialize(aliases);
        }

        for (int a=0;a<aliases.length;a++){

            String alias = aliases[a];
            Object tuple = tuples[a];

            Object baseObject = result;

            int index = alias.lastIndexOf(".");
            if(index>0){
                String basePath = alias.substring(0, index);
                baseObject = nestedObjectsMap.get(basePath);
                if (baseObject == null){
                    baseObject = clazzMap.get(basePath).newInstance();
                    nestedObjectsMap.put(basePath, baseObject);
                }
            }

            settersMap.get(alias).set(baseObject, tuple,null);

        }

        for (Entry<String,Object> entry:nestedObjectsMap.entrySet()){
            Setter setter = settersMap.get(entry.getKey());
            if (entry.getKey().contains(".")){

                int index = entry.getKey().lastIndexOf(".");
                String basePath = entry.getKey().substring(0, index);
                Object obj = nestedObjectsMap.get(basePath);

                setter.set(obj, entry.getValue(), null);
            }
            else{
                setter.set(result, entry.getValue(), null);
            }
        }

    }catch ( InstantiationException | IllegalAccessException e) {
        throw new HibernateException( "Could not instantiate resultclass: " + resultClass.getName() );
    }

    return result;
}


private void initialize(String[] aliases) {

    PropertyAccessor propertyAccessor = new ChainedPropertyAccessor(
            new PropertyAccessor[] {
                    PropertyAccessorFactory.getPropertyAccessor( resultClass, null ),
                    PropertyAccessorFactory.getPropertyAccessor( "field" )
            }
    );

    for (int a=0;a<aliases.length;a++){

        String alias = aliases[a];

        Class<?> baseClass = resultClass;

        if (alias.contains(".")){

            String[] split = alias.split("\\.");

            StringBuffer res = new StringBuffer();

            for (int i=0;i<split.length;i++){

                if (res.length()>0) res.append(".");

                String item = split[i];
                res.append(item);

                String resString = res.toString();

                if (i==split.length-1){
                    clazzMap.put(resString,baseClass);
                    settersMap.put(resString, propertyAccessor.getSetter(baseClass, item));
                    break;
                }

                Class<?> clazz = clazzMap.get(resString);
                if (clazz==null){
                    clazz = propertyAccessor.getGetter(baseClass,item).getReturnType();
                    settersMap.put(resString, propertyAccessor.getSetter(baseClass, item));
                    clazzMap.put(resString,clazz);
                }
                baseClass = clazz;
            }
        }
        else{
            clazzMap.put(alias, resultClass);
            settersMap.put(alias, propertyAccessor.getSetter(resultClass, alias));
        }

    }

}
公共类别名ToBeanNestedMultilevelResultTransformer扩展了别名TupleSubstreSultTransformer{
私有静态最终长serialVersionUID=-8047276133980128266L;
公共布尔值isTransformedValueATupleElement(字符串[]别名,int-tupleLength){
返回false;
}
私有布尔初始化;
私有类resultClass;
私有映射基类=resultClass;
if(别名为.contains(“.”){
String[]split=alias.split(“\\”);
StringBuffer res=新的StringBuffer();
对于(inti=0;i0)res.append(“.”);
字符串项=拆分[i];
附加(项目)决议;
字符串resString=res.toString();
如果(i==split.length-1){
clazzMap.put(resString,基类);
settersMap.put(resString,propertyAccessor.getSetter(基类,项));
打破
}
Class clazz=clazzMap.get(resString);
if(clazz==null){
clazz=propertyAccessor.getGetter(基类,项).getReturnType();
settersMap.put(resString,propertyAccessor.getSetter(基类,项));
clazzMap.put(resString,clazz);
}
baseClass=clazz;
}
}
否则{
clazzMap.put(别名,resultClass);
setterMap.put(别名,propertyAccessor.getSetter(resultClass,别名));
}
}
}

}我的解决方案非常基本。它不像一个合适的结果转换器那样干净,但是当您只需要对一些属性进行快速投影时,它非常有用

代替
.add(Projections.property(“关税.金额”),“金额”)
键入
.add(Projections.property(“关税金额”),“关税金额”)

然后,只需在根对象“setTariffAmount”上添加一个setter


缺点是它会用额外的方法“弄脏”你的对象。

如果我有person类中的汽车对象列表,仍然可以使用AliasToBeanNestedResultTransformer?@hadi,是和否。你仍然可以使用
AliasToBeanNestedResultTransformer
来处理
OneToMany(又名Collections)
,但结果将是每个子对象的单个父行
。因此,您将无法将其作为父对象内的集合获取,而只能作为每个子行的单独父对象。我也在寻找能支持OneToMany(又名Collections)
别名BeannestedResultTransformer
。对于任何可能偶然发现这个答案的人,Miguel Resendiz的原始答案已经更新,以适应
OneToMany
案例。在此处签出-也签出此线程:
public class AliasToBeanNestedMultiLevelResultTransformer extends AliasedTupleSubsetResultTransformer {

private static final long serialVersionUID = -8047276133980128266L;

public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
    return false;
}

private boolean initialized;
private Class<?> resultClass;
private Map<String,Class<?>> clazzMap = new HashMap<>();
private Map<String,Setter> settersMap = new HashMap<>();

public AliasToBeanNestedMultiLevelResultTransformer(Class<?> resultClass) {
    this.resultClass = resultClass;
}

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

    Map<String,Object> nestedObjectsMap = new HashMap<>();

    Object result;
    try {
        result = resultClass.newInstance();

        if (!initialized){
            initialized = true;
            initialize(aliases);
        }

        for (int a=0;a<aliases.length;a++){

            String alias = aliases[a];
            Object tuple = tuples[a];

            Object baseObject = result;

            int index = alias.lastIndexOf(".");
            if(index>0){
                String basePath = alias.substring(0, index);
                baseObject = nestedObjectsMap.get(basePath);
                if (baseObject == null){
                    baseObject = clazzMap.get(basePath).newInstance();
                    nestedObjectsMap.put(basePath, baseObject);
                }
            }

            settersMap.get(alias).set(baseObject, tuple,null);

        }

        for (Entry<String,Object> entry:nestedObjectsMap.entrySet()){
            Setter setter = settersMap.get(entry.getKey());
            if (entry.getKey().contains(".")){

                int index = entry.getKey().lastIndexOf(".");
                String basePath = entry.getKey().substring(0, index);
                Object obj = nestedObjectsMap.get(basePath);

                setter.set(obj, entry.getValue(), null);
            }
            else{
                setter.set(result, entry.getValue(), null);
            }
        }

    }catch ( InstantiationException | IllegalAccessException e) {
        throw new HibernateException( "Could not instantiate resultclass: " + resultClass.getName() );
    }

    return result;
}


private void initialize(String[] aliases) {

    PropertyAccessor propertyAccessor = new ChainedPropertyAccessor(
            new PropertyAccessor[] {
                    PropertyAccessorFactory.getPropertyAccessor( resultClass, null ),
                    PropertyAccessorFactory.getPropertyAccessor( "field" )
            }
    );

    for (int a=0;a<aliases.length;a++){

        String alias = aliases[a];

        Class<?> baseClass = resultClass;

        if (alias.contains(".")){

            String[] split = alias.split("\\.");

            StringBuffer res = new StringBuffer();

            for (int i=0;i<split.length;i++){

                if (res.length()>0) res.append(".");

                String item = split[i];
                res.append(item);

                String resString = res.toString();

                if (i==split.length-1){
                    clazzMap.put(resString,baseClass);
                    settersMap.put(resString, propertyAccessor.getSetter(baseClass, item));
                    break;
                }

                Class<?> clazz = clazzMap.get(resString);
                if (clazz==null){
                    clazz = propertyAccessor.getGetter(baseClass,item).getReturnType();
                    settersMap.put(resString, propertyAccessor.getSetter(baseClass, item));
                    clazzMap.put(resString,clazz);
                }
                baseClass = clazz;
            }
        }
        else{
            clazzMap.put(alias, resultClass);
            settersMap.put(alias, propertyAccessor.getSetter(resultClass, alias));
        }

    }

}
public void setTariffAmount(String tariffAmount) {
  this.tariff = (this.tariff==null) ? new Tariff() : tariff;
  tariff.setAmount(tariffAmount);
}