欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何解决 hibernate 自动更新实体类的问题

程序员文章站 2022-04-16 15:15:11
...

如何解决 hibernate 自动更新实体类的问题

示例:

GrabOrder grabOrder = (GrabOrder)this.grabOrderDao.getCurrentSession().get(GrabOrder.class,grabOrderId);
grabOrder.setNickname(TimeHWUtil.getCurrentDateTime());

 

上述代码 会执行两条SQL:

查询和更新

为什么会更新呢?我明明没有调用DAO的update方法啊!!!

但是这里我调用了实体类的setter方法,

hibernate有一个机制:Hibernate dirty-checks,会同步session缓存和数据库的数据.

如何解决 自动更新的问题:

方案一:把实体类由持久态变为脱管态(游离态)

this.grabOrderDao.getCurrentSession().evict(grabOrder);

 缺点:懒加载的对象无法加载,因为此时session相当于close

而且会报错:org.hibernate.LazyInitializationException: could not initialize proxy - no Session

报错的代码:

this.grabOrderDao.getCurrentSession().clear();
        System.out.println(grabOrder.getHouseInfo().getHouseOwner().getId());

 

 

更好的操作步骤:

(1)先把要访问的属性加载出来,可以通过提前使用,或者Hibernate.initialize(dept)

(2)再调用evict方法或clear方法

什么叫提前使用呢?即提前调用getter方法

正确:

System.out.println(grabOrder.getHouseInfo().getHouseOwner().getId());
        this.grabOrderDao.getCurrentSession().clear();
        System.out.println(grabOrder.getHouseInfo().getHouseOwner().getId());

 

 

方案二:把实体类变为只读

this.grabOrderDao.setReadOnly(grabOrder, readonly);

 但是这招不是万灵药,有例外,看官网:

12.2.2.2. Unidirectional one-to-many and many-to-many
Hibernate treats unidirectional one-to-many and many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.

修改 单向的一对多和多对多的成员变量时,依然会触发hibernate的自动更新.

有什么万全之策呢?

(a)采用读写分离,把操作放在只读的数据库连接

 

(b)采用只读事务

当方法名是updateTestLazy 时会自动更新

但是我修改方法名为getTestLazy时,就不会自动更新了

为什么呢?看看spring 事务配置


如何解决 hibernate 自动更新实体类的问题
            
    
    博客分类: hibernate数据库 事务管理持久态自动更新懒加载 
 

只读的对象 不保险,所以我们使用只读的事务或只读的数据库连接.

 

如何解决 json序列化时,自动加载lazy对象导致对象多层嵌套的问题?

使用 SimpleBeanPropertyFilter过滤不需要的字段

 /***
     *
     * @param xpath : 参考 com/kunlunsoft/util/objectxpath/ObjectXpath.java
     * @return
     */
    public String toJson(String column, String... xpath) {
        if (this.result == null) {//modified by huangweii @2015-08-17
            System.out.println("this.result is null");
        } else {
            if (this.result != false) {
//                this.errorMessage = null;
                this.setErrorMessage(null);
            }

        }
        if (ValueWidget.isNullOrEmpty(xpath)
                || ValueWidget.isNullOrEmpty(xpath[0])) {
            return HWJacksonUtils.getJsonP(this);
        }

//        final ObjectXpath oxp = new ObjectXpath();
        int length = xpath.length;
//        final Object[] filterObjects = new Object[length];
        List filterObjList = new ArrayList();
        for (int i = 0; i < length; i++) {
            Object o = XPathParser.process(this.getValue(), xpath[i]);
            if (o instanceof List) {
                filterObjList.addAll((List) o);
            } else {
                filterObjList.add(o);
            }
//            filterObjects[i] = o;
        }
        final Object[] filterObjects = filterObjList.toArray();
        return HWJacksonUtils.getJsonP(this, new DefaultJsonFilterDecide() {
            @Override
            public boolean isFilteColumn(Object pojo, Object propertyVal, String column2) {
                if (ValueWidget.isNullOrEmpty(column)) {
                    if (SystemHWUtil.isEquals(propertyVal, filterObjects)) {
                        return true;
                    }
                } else {
                    if (SystemHWUtil.isEquals(pojo, filterObjects) && (column2.equals(column))) {
                        return true;
                    }
                }
                return false;
            }
        });
    }

 

 

  • 如何解决 hibernate 自动更新实体类的问题
            
    
    博客分类: hibernate数据库 事务管理持久态自动更新懒加载 
  • 大小: 356.9 KB