Reputation: 6620
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;
...
}
Upvotes: 1
Views: 652
Reputation: 4310
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?
Upvotes: 1