Wednesday, January 27, 2010

enum != Enum

All enumerations automatically contain two predefined methods: values( ) and valueOf( ).

1. public static enum-type[ ] values( )
2. public static enum-type valueOf(String str)

These two methods are not in Enum API.


enum Week {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturaday, Sunday
}

Week allWeek[] = Week.values();

Wednesday, January 20, 2010

Bag vs. List


public class FilterGroup {
private List<Fitler> filters = new ArrayList<Fitler>();
...
}








I mapped List as above but got bizarre result. Although there are only 8 items in the list, it returned a list with over 1000 item and most of them are null. It turns out this is because the column "orderPos" used for list index contains a big number 1025+.

I do want a sorted list. So I change to use bag mapping with order-by. It works well. In Hibernate document, it said bag is mapped for Collection. Internally it is implemented as ArrayList but ignores index (Bag is different from set in that it allows duplicates). So I can map it to List as well and add a order-by to sort it in database level. (set, map, bag all can have order-by)






Also, note that we need "delete-orphan" cascade for collection. So when we do a update on FilterGroup, the filters removed from the collection will be deleted from database automatically. Otherwise, it will still remain.

Monday, January 11, 2010

Session.get() return proxy?

Surprising, the object returned by session.get() is a proxy rather than the real object. What is going on?

Hibernate API said Session.load(id) return a proxy and Session.get(id) return a persistent object. But actually get() may return proxy if previously it is lazily loaded in the same session, e.g., as a property of other object. A proxy is a proxy even you have called its methods.

Typecasting and instanceof work well for proxy object, however, there is a pitfall, for super-class or interface, it will not give you the implementation class. e.g., it is instanceof Template, but not instanceof VnsTemplate.

To ensure we always get the real persistent object, I implement read() in Dao as follows:


public T read(int id) {
T obj = (T)getSession().get(entityClass, id);

if (obj instanceof HibernateProxy) {
return(T) ((HibernateProxy)obj).getHibernateLazyInitializer().getImplementation();
}

return obj;
}

Alternatively, HibernateProxyHelper.getClassWithoutInitializingProxy(o) could be used to get class info.

Note that we couldn't use session.evict() to detach old proxy object and call get() to retrieve the real object. The old proxy object will still be referenced by other object, and access to its member may throw LazyInitializationException even inside the transaction since it has been detached.