Pergunta

I have a class which has a list of member objects, I need to just retrieve a few fields of the member object, how can I do it? When I execute the generated query it just shows those records which has both owner and user, those that do not have one of these would not be included in the query result.

@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;


    ...
}

I need to retrieve id of the category along with all fields of the Product BUT just firstname of the owner and the user.

I have the following code but it seems it is wrong as there is a list of products for each category.

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);

Result should be as following

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;
    ...
}
Foi útil?

Solução

You should try to replace the AliasToBeanResultTransformer in your code with this custom one:

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.

I think it's meant to be @OneToMany in this fragment of your code:

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

Isn't it?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top