【问题标题】:Using Projecions to fetch a particular column from child table使用投影从子表中获取特定列
【发布时间】:2015-05-02 00:20:48
【问题描述】:

我有两张桌子

Loan (id, amount, duration)

LoanStatus(id, status, loan_id)   // just an example, but it has lot more fields in this table

Loan.java

public class Loan{

    private int id;
    private int amount;
    private int duration;
    private LoanStatus loanStatus;

    // getter and setters

}

LoanStatus.java

public class LoanStatus{   // just an example, but it has many fields than what actually given

    private int id;
    private String status;
    private Loan loan;

    //getter and setters

}

现在我只想使用 Projections 获得 amountdurationloanStatus.status 。我已经使用createAlias() 成功获取了该特定列,但是将其设置为 setter 时会出现问题。

Criteria criteria = getSession().createCriteria(Loan.class,"loan");
    criteria.createAlias("loan.loanStatus", "loanStatus")
            .setProjection(Projections.projectionList().add(Projections.property("id"),"id")
            .add(Projections.property("amount"),"amount")
            .add(Projections.property("duration"),"duration")
            .add(Projections.property("loanStatus.status"), "loanStatus"))
            .add(Restrictions.eq("id", id))
            .setResultTransformer(Transformers.aliasToBean(Loan.class));
    return criteria.list();

我的错误如下。

IllegalArgumentException occurred while calling setter for property [com.site.dto.Loan.loanStatus (expected type = com.site.dto.LoanStatus)]; target = [com.site.dto.Loan@4083974a], property value = [Pending]

所以我得到了我预期的列值“Pending”,但问题在于将其设置为 setter 时。我见过很多关于投影的问题,但其中大部分是基于使用投影的限制,而不是使用投影获取孩子的特定列。

【问题讨论】:

    标签: java mysql hibernate projection


    【解决方案1】:

    编写您自己的自定义转换器。以下实现可能正是您所需要的

    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
    

    【讨论】:

    • 但恰恰相反,我将loanStatus 作为loan 类中的一个对象,用于一对一映射以及基于状态的简单限制。坦率地说,我只需要来自 loanStatus 对象的状态字段,但它应该可以作为 loanStatus 对象使用,而不仅仅是一个字符串,因为我还有一些进一步的 jaxb XML 转换
    • 我已经编辑了一个答案,没有注意到 Loan 类也是一个实体,我认为它是一个简单的数据传输对象
    • 谢谢.. 我也想过。但是我在贷款状态中有很多状态,所以我认为为每个状态创建瞬态字段并不是一个好习惯。我只是想知道是否可以将孩子的特定字段作为子对象而不是在父对象中创建一个瞬态字段。
    • 例如,如果我调用loan.getLoanStatus().getStatus(),它应该返回状态。但是如果我调用loan.getLoanStatus().getSomeOtherFields(),它应该返回null。这是我的预期输出。就像使用投影仅获取父表中的几列一样,我也应该能够仅获取子 AS 子对象中需要的列,但不能获取父对象中的字段
    • 正要建议编写一个自定义转换器,并在网上找到了一个您最有可能按原样使用的实现
    猜你喜欢
    • 2011-02-16
    • 1970-01-01
    • 2021-06-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    相关资源
    最近更新 更多