Nambari Nambari - 15 days ago 5
Java Question

Hibernate partially populated object with projections

My question is same exact issue like this SO question.

Assume we have entity like

public class Employee {
Long getId();
String getName();
Address getAddress();
}


With the help of createCriteria and Projections we are trying to get id,name from users and city from address table.

The issue we are having is, city is not being set to address object city property.

Here is the code we tried:

Criteria cr = session.createCriteria(Employee.class)
.setProjection(Projections.projectionList()
.add(Projections.property("id"), "id")
.add(Projections.property("Name"), "Name")
.add(Projections.property("address.city"), "address.city"))
.addOrder(Order.asc("address.city"))
.createAlias("address", "address")
.setResultTransformer(Transformers.aliasToBean(Employee.class));


Based on
JBNizet
comment on above question I understood that partially objects are bad idea, but If I am mandated to do that how can I achieve it? Any input would be appreciated.

Answer

Use an AliasToBeanConstructorResultTransformer, and define a constructor like the following in your entity:

public Employee(Long id, String name, String city) {
    this.id = id;
    this.name = name;
    this.address = new Address();
    this.address.setCity(city);
}

Or, (and this is my preferred solution, because it avoids reflection and allows refactoring the code with less risk) dont't use any result transformer and construct your instances yourself:

List<Object[]> rows = criteria.list();
List<Employee> result = new ArrayList<Employee>(rows.size());
for (Object[] row : rows) {
    Employee e = new Employee();
    e.setId((Long) row[0]);
    e.setName((String) row[1]);
    Address address = new Address();
    address.setCity((String) row[2]);
    e.setAddress(address);
    result.add(e);
}