如何在成员对象的特定字段上应用投影?

时间:2014-04-09 05:38:25

标签: java hibernate hibernate-mapping

我有一个有成员对象列表的类,我需要只检索成员对象的几个字段,我该怎么办?当我执行生成的查询时,它只显示那些同时拥有所有者和用户的记录,那些没有这些记录的记录将不会包含在查询结果中。

@Entity
public class Category implements Serializable {

    @Id
    @GeneratedValue
    private long id;
    @OneToOne
    private List<Product> products = new ArrayList()

    ...
}

@Entity
public class Product {

    @Id
    @GeneratedValue
    private long id;
    private float price;
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date regDate;
    @OneToOne
    private Person owner;
    @OneToOne
    private Person user;


    ...
}

我需要检索该类别的ID以及Product BUT的所有字段,只是所有者和用户的名字。

我有以下代码,但似乎是错误的,因为每个类别都有一个产品列表。

Criteria cre = session.createCriteria(Category.class, "cat")
                    .createAlias("cat.products", "pro")
                    .createAlias("pro.owner", "owner")
                    .createAlias("pro.user", "user")
                    .addOrder(Property.forName("pro.id").asc());
            ProjectionList pl = Projections.projectionList();
            pl.add(Projections.property("cat.id").as("cid"));
            pl.add(Projections.property("pro.id").as("pid"));
            pl.add(Projections.property("pro.price").as("price"));
            pl.add(Projections.property("pro.regDate").as("date"));
            pl.add(Projections.property("owner.fname").as("owFname"));
            pl.add(Projections.property("owner.lname").as("owLname"));
            pl.add(Projections.property("user.fname").as("usFname"));
            pl.add(Projections.property("user.lname").as("usLname"));
            cre.setProjection(pl);

criteria.setResultTransformer(new AliasToBeanResultTransformer(CategoryResult.class));
categoryResult = (CategoryResult) criteria.list().get(0);

结果应如下

public class CategoryResult {


    private long cid;
    private List<ProductResults> products = new ArrayList()

    ...
}

public class ProductResults {


    private long pid;
    private float price;
    private Date regDate;
    private String owFname;
    private String owLname;
    private String usFname;
    private String usLname;
    ...
}

1 个答案:

答案 0 :(得分:1)

您应该尝试使用以下自定义代码替换代码中的AliasToBeanResultTransformer

public class CategoryResultTransformer extends AliasToBeanResultTransformer {
    public static final String CID_ALIAS = "cid";
    private int cidIndex = -1;

    public CategoryResultTransformer() {
        super(ProductResults.class);
    }

    @Override
    public Object transformTuple(Object[] tuple, String[] aliases) {
        if (cidIndex < 0) {
            for (int i = 0; i < aliases.length; ++i) {
                if (CID_ALIAS.equals(aliases[i])) {
                    cidIndex = i;
                    break;
                }
            }
        }

        return new Object[] { tuple[cidIndex], super.transformTuple(tuple, aliases) };
    }

    @Override
    public List transformList(List list) {
        List<CategoryResult> res = new ArrayList<CategoryResult>();
        Map<Long, CategoryResult> map = new HashMap<Long, CategoryResult>();

        for (Object[] row : (List<Object[]>)list) {
            long cid = ((Number)row[0]).longValue();
            CategoryResult cat = map.get(cid);

            if (cat == null) {
                cat = new CategoryResult();
                cat.setCid(cid);
                res.add(cat);
                map.put(cid, cat);
            }

            cat.getProducts().add((ProductResults)row[1]);
        }

        return res;
    }
}

<强> P.S。

我认为这段代码中的@OneToMany意味着:

@OneToOne
private List<Product> products = new ArrayList()

不是吗?