3

I'm using Spring to develop my application using Hibernate and JPA as persistence API in a MySQL database. When I fetch most of my objects from the database, they have their attributes initialized with the values of the database and collections are Lazy loaded. The problem comes with an entity called Business which is loaded as a JavassistLaziInitializer using method find() from EntityManager.

If I execute a get or set method, they use the proxy and give me the values I need, but when I use @Valid and validation annotaions, as the real values are NULL (column values, not collections), I have validation errors like @NotNull.

I was hoping if somebody knows a method to get the columns filled with the JavassistLazyInitializer proxy values, or a method to get the proxy itself.

Note that this behaviour, as I have concerned is not a bug on hibernate because it has been reported several times as a bug but developers advices that is a normal behaviour of hibernate that happend in certain conditions.

4

1 回答 1

11

对于(如您所说)某些类型的代码,我使用“deproxy()”和其他几个辅助函数。

这使得 Spring 的“自动增长”路径绑定工作,在通过 Hibernate 加载可能的子类实体时检查实际类型以及代理导致事情中断的各种其他有趣的极端情况是必要的。

public class HbUtils {

    public static <T>  T deproxy (T obj) {
        if (obj == null)
            return obj;
        if (obj instanceof HibernateProxy) {
            // Unwrap Proxy;
            //      -- loading, if necessary.
            HibernateProxy proxy = (HibernateProxy) obj;
            LazyInitializer li = proxy.getHibernateLazyInitializer();
            return (T)  li.getImplementation();
        } 
        return obj;
    }


    public static boolean isProxy (Object obj) {
        if (obj instanceof HibernateProxy)
            return true;
        return false;
    }

    // ----------------------------------------------------------------------------------


    public static boolean isEqual (Object o1, Object o2) {
        if (o1 == o2)
            return true;
        if (o1 == null || o2 == null) 
            return false;
        Object d1 = deproxy(o1);
        Object d2 = deproxy(o2);
        if (d1 == d2 || d1.equals(d2))
            return true;
        return false;
    }

    public static boolean notEqual (Object o1, Object o2) {
        return ! isEqual( o1, o2);
    }

    // ----------------------------------------------------------------------------------

    public static boolean isSame (Object o1, Object o2) {
        if (o1 == o2)
            return true;
        if (o1 == null || o2 == null) 
            return false;
        Object d1 = deproxy(o1);
        Object d2 = deproxy(o2);
        if (d1 == d2)
            return true;
        return false;
    }

    public static boolean notSame (Object o1, Object o2) {
        return ! isSame( o1, o2);
    }



    // ----------------------------------------------------------------------------------

    public static Class getClassWithoutInitializingProxy (Object obj) {
        if (obj instanceof HibernateProxy) {
            HibernateProxy proxy = (HibernateProxy) obj;
            LazyInitializer li = proxy.getHibernateLazyInitializer();
            return li.getPersistentClass();
        } 
        // Not a Proxy.
        return obj.getClass();
    }

}

我在每个主要的 Hibernate 项目中都使用这样的类。PS:这不是我唯一的 Hibernate 助手——我有一个用于一般获取 ID 并检查实体是否是新的/存在的。

希望这可以帮助!

于 2013-05-05T10:58:26.727 回答