hibernate - virtual column for Criteria query

5.3k Views Asked by At

I've created an entity called Person. It implements Lifecycle interface. The onLoad method sets the department property. Sometimes a department is unknown (== null).

@Entity
@Table(name = "PERSON")
public class Person implements Lifecycle {

   @Column(name = "NAME", length = 128, columnDefinition = "VARCHAR2(128)")
   String name;

   @Transient
   Department department;

   public void onLoad(Session s, Serializable id) {
      // some logic resolving department
   }
}

Is there any way to make the department property a virtual column (or something like this) - never created in the database.

@Entity
@Table(name = "PERSON")
public class Person {

   @Column(name = "NAME", length = 128, columnDefinition = "VARCHAR2(128)")
   String name;

   @Type(type = "DepartmentType") // UserType for resolving a department
   //@Transcient
   //@Column(insertable = false, updatable = false)
   //@NotFound(action = NotFoundAction.IGNORE)
   // ... don't have a clue
   Department department;
}

I would like to have the ability to use Criteria.

Criteria criteria = session.createCriteria(Person.class);
criteria.add(Restrictions.isNotNull("department"));
List<Person> list = criteria.list();

I understand that Criteria executes before finding the department, so the property 'department' could not be resolved.

I've seen that I can remove a row from UserType's nullSafeGet

public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
   rs.deleteRow();
}

but I don't want to delete the row from database (it's read-only!).

To sum up my questions are:

1) Is it possible to create a virtual column?

2) Is there any more efficient way of doing this?

Criteria criteria = session.createCriteria(Person.class);
// ... some restrictions ...
List<Person> list = criteria.list();
Iterator<EbamLogMessageEntity> it = list.iterator();
while(it.hasNext()) {
    Person p = it.next();
    Department d = resolveDepartment(p)
    if(d == null) {
    it.remove();
} else {
        p.setDepartment(d);
    }
}
1

There are 1 best solutions below

3
On

It's possible, if you can express the content of the virtual column as a SQL formula, using the @Formula annotation. See the documentation for more details. If the virtual column is a virtual join column, you may also use the @JoinFormula annotation.