Hibernate reading function shows old data

前端 未结 4 756
梦如初夏
梦如初夏 2020-12-15 12:21

I\'ve a problem showing data from database. If I update an object, sometimes I get the old data, sometimes the new one. Update function works well (I can see in DB the right

相关标签:
4条回答
  • 2020-12-15 12:44

    I have the same problem, my query select * returning old data. I have in my hibernate.cfg.xml file turned off 2nd level cache like this

    <property name="hibernate.cache.use_second_level_cache">false</property>
    <property name="hibernate.cache.use_query_cache">false</property>
    <property name="hibernate.c3p0.max_statements">0</property>
    

    I'll try add session.flush() or session.clear() before/after transaction.commit() but it not gives positive result

    0 讨论(0)
  • 2020-12-15 12:51

    You can open a new session in order to get "fresh"(updated from database) data without old entities from session cache. In the example below you can see as an entity is being querying from database. Also you can use the same mechanism to return the entity instead of a boolean value, or call session.Refresh() (from your current session of course) to refresh latest changes from database:

            /// <summary>
            ///  Gets an item exists on database.
            /// </summary>
            /// <param name="Id">Item ID to check if exists on database</param>
            /// <returns> True if the <paramref name="Id"/> to check exists on database, otherwise false. </returns>
            public bool Exists<T>(object Id)
            {
                using (var session = NHibernateSessionHelper.OpenSession())
                {
                    using (var transaction = session.BeginTransaction())
                    {
                        //get if the item is new. If is new, entity will be null and non exists
                        return session.Get<T>(Id) == null ? false : true;
                        //also you can return the entire table from database, or filter:
                        //session.CreateCriteria<T>().List<T>();
                    }
                }
            }
    
            public void Refresh(object entity)
            {
                //get latest changes from database (other users/sessions changes, manually, etc..) 
                NHibernateSessionHelper.CurrentSession.Refresh(entity);
            }
    

    I hope this helps you.

    0 讨论(0)
  • 2020-12-15 12:54

    Usually, you have an isolation level "read committed". This lets your transaction see changes that have been committed by other transaction. The isolation level is implemented by the underlying dbms, not by hibernate.

    You can't disable the first level cache (probably by using the stateless session, which shouldn't be used for general purposes). When executing a query, NH always returns values from the cache when it is found there, to ensure that you don't get the same db record more then once in memory.

    If this is an issue for you, you should switch to a higher isolation level. For instance repeatable read (which means what it says: when reading the same data several times, you always get the same result). There is still the chance to see changes from other transaction. Using isolation level serializable, you shouldn't have this kind of issue anymore.

    Note: switching to another isolation level is a breaking change to most systems and should be planned carefully.

    0 讨论(0)
  • 2020-12-15 12:55

    You may evict old data so as to ensure that data is fetched from db and not from L1 and L2 caches.

    Also you have to make sure your are not in a REPEATABLE_READ isolation level. In this isolation mode, it guarantees that two reads within the same transaction will always return the same result. As the isolation level takes precedence on your cache eviction, the cache evict will not have any visible effect.

    There is a ways to work around this behavior: Declare your transaction isolation level to READ_UNCOMMITTED or READ_COMMITTED.

    0 讨论(0)
提交回复
热议问题