Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate AliasToBean with Collection

I have a bi-directional one-to-many relationship defined between Parent and Child classes. I'm looking to execute a query such that I can return a single parent, and a subset of its children in a bean.

public class Parent {
    private int id;
    private Set<Child> children = new HashSet<Child>(0);

    // other fields + getters and setters
}

public class Child {
    private Parent parent;
    private int age;

    // other fields + getters and setters
}

The output I'm looking to achieve is:

public class ParentChildWrapper {
    private Parent parent;
    private Collection<Child> children; // subset of children
}

I'd like to filter on the parent's id and the child's age column. I've tried a number of query combinations in order to get the desired output.

The following is close, but doesn't group the children in a collection in the ParentChildWrapper bean I've defined. The result I get is a list of objects, with 1 instance per child that matches the age filter:

Query q = session.createQuery(
    "SELECT p, c " +
    "FROM Parent p " +
    "INNER JOIN p.children c " +
    "WHERE p.id = :id " +
    "AND c.age = :age"
);

I've also tried to group by the parent in order to try and aggregate all the children into a collection, also to no avail.

Obviously I could separate this into two separate queries in order to select the parent, and then select the children that I want. But it feels like this should be a fairly common use case. Perhaps I'm not thinking in a hibernate-esque way.

like image 886
Michael Avatar asked Oct 11 '22 01:10

Michael


1 Answers

Just don't use any transformer and code the loop yourself:

List<Object[]> rows = query.list();
Parent parent = null;
List<Child> children = new ArrayList<Child>(rows.size());
for (Object[] row : rows) {
    parent = (Parent) row[0];
    children.add((Child) row[1]);
}
ParentChildWrapper result = new ParentChildWrapper(parent, children);

This makes 8 lines of trivial code instead of 1, but avoids reflection calls, and thus allows safe refactoring.

like image 143
JB Nizet Avatar answered Oct 13 '22 16:10

JB Nizet