Colleagues summarize the cool problem of hibernate updating data unexpectedly.
To action developers:
Since it was discovered a few days ago that after the Bean taken out from the database is modified, the modified result will be reflected in the database again, and the following analysis and solution are proposed.
reason:
Under normal circumstances, after the Service ends, the transaction ends. At this time, the Hibernate Session should disappear, however, because the data provides lazy loading
Therefore, it is necessary to provide a Session in the Web layer to load data. At this time, the life cycle of the Session needs to be extended. Spring
Provides the OpenSessionInViewFilter class, when a web request comes in, the request is assigned a Hibernate Session to the request thread
Up until the end of the request, at this time we retrieve a piece of information from the database to the Controller layer through the Manager, no matter how it is modified in the Controller layer,
will not be synchronized to the database, because the default session refresh method is AUTO (re-retrieving data, submitting transactions, refreshing data will activate the data synchronization function),
However, under normal circumstances, we use other Manager methods to activate the same Session after modification, so that the refresh event in the Session is activated,
The consequence of this is that Hibernate submits the modified data as legitimate dirty data. Causes the value in the database to be modified. That is, the database
The data in has been modified. This is because everyone uses the methods in the manager multiple times in the same request. Before the manager method is used for the last time, the
Data Beans were modified.
Solution:
Since the bean is managed in hiberante, if it is instantiated, the data will not be stored in the hiberante cache, and it will be retrieved from the database again, so that even if we
Modifying it doesn't help, so I'll propose a workaround now.
YHB.DISABLE_SYNC (a constant in YHB), marks an object to disable synchronization with objects in the database.
When we retrieve a piece of information from the database, the data in the object is modified for some reason, and we do not want to synchronize it to the database, please execute the object's
Bean.setVersion(YHB.DISABLE_SYNC), you can prohibit the object from modifying the database. This method is only useful for automatically submitting updates. Manually calling the update method is invalid.
After using this method in the background, it still insists on calling the update object, which will cause the version out-of-sync exception to occur. The object that works in this way is only for persistent objects in Session that do not want to be updated
It works, please confirm whether it is necessary to use it.
example:
UkeMember member = manager.findById(1); // Get a member
Integer version = member.getVersion(); // Temporarily store the version number of the member object,
// If there is no concept of version number in the foreground, it can be ignored
member.setVersion(YHB.DISABLE_SYNC); // Prevent the object content from synchronizing with the database object
member.setName("hello"); // Modify the content of the object
promotionRuleMng.initPromotionRules(member); // The session is activated again, and the object survives to the session.
// The data is synced to the database as it is.
member.setVersion(version); // restore the original version number
Assert.assertTrue("liutie".equals(name)); // verify or return
The above functions have been implemented, please pay attention to the update.