使用自定义BeanUtils.copyProperties方法会导致Hibernate删除Collection

时间:2014-05-06 16:38:14

标签: spring hibernate apache-commons-beanutils

我将org.apache.commons.beanutils.BeanUtilsBean子类化,以便忽略NULL属性:

public class NullAwareBeanUtilsBean extends BeanUtilsBean {

    Logger log = Logger.getLogger(this.getClass());

    @Override
    public void copyProperty(Object dest, String name, Object value) throws IllegalAccessException, InvocationTargetException {

        if (value == null) {
            log.debug("skipping property " + name);
            return;
        }
        super.copyProperty(dest, name, value);

    }


}

我的用户类有一个Stats集合:

public class User implements Serializable{

private Integer id;
private String username;
private Set<Stat> stats = new HashSet<Stat>();

}

如果我这样做,它可以正常工作:

    public void updateUser(User user) {        
    User dbUser = userDao.read(user.getId());
    dbUser.setUsername(user.getUsername());
    log.debug("about to save" + dbUser);
    userDao.update(dbUser);
}

但是如果我使用copyProperties(),它认为Set of Stats是空的并试图删除它:

public void updateUser(User user) {
        User dbUser = userDao.read(user.getId());

    //the problem here is that hibernate does not like the copyProperties method...

    try {
        NullAwareBeanUtilsBean nullAwareBeanUtilsBean = new NullAwareBeanUtilsBean();
        nullAwareBeanUtilsBean.copyProperties(dbUser, user);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

    //dbUser = (User) userDao.getCurrentSession().merge(dbUser);
    //log.debug("stats size=" + dbUser.getStats().size());

    log.debug("about to save" + dbUser);
    userDao.update(dbUser); }

我已经尝试过使用Hibernate.initialize(),以及在使用BeanUtils之前和之后引用Set来初始化Set(如果之前调用它会这样做),但它并不重要,因为它是空的之后(即使我重新初始化)...我也尝试将它合并到会话中,但这也没有用。有什么想法吗?我认为它可能与Hibernate创建一个代理对象有关,而BeanUtils却以某种方式弄乱了它。

1 个答案:

答案 0 :(得分:0)

我认为问题可能是“user”有一个空集(非null对象),因此copyProperties将空的“user”集复制到现有的Set中,其值为“dbUser”(所以,当你保存dbUser,你正在清理Set)。如果您还想要防止复制和空集,可以将方法更改为:

public void copyProperty(Object dest, String name, Object value) throws IllegalAccessException, InvocationTargetException {

        if (value == null) {
            log.debug("skipping property " + name);
            return;
        }
        if ((value instanceof Set) && ((Set) value).isEmpty()) {
            log.debug("skipping empty Set" + name);
            return;
        }
        super.copyProperty(dest, name, value);

    }