This is an exception encountered when a transaction is committed.
An assertion failure occured (this may indicate a bug in hibernate, but is more likely due to unsafe use of the session)
Net. SF. hibernate. assertionfailure: Possible nonthreadsafe ACCESS TO SESSION
Note: Non-possible non-threadsafe access to the session (that is another error, similar but different)
This exception should have been encountered by many friends for different reasons. However, all exceptions should occur during flush or transaction commit. This is generally caused by incorrect operations from the beginning of the transaction to the transaction commit process, and also occurs when multiple threads operate on a session at the same time. Here we only discuss the single thread situation, in addition to thread synchronization, multithreading is basically the same.
What error operations are specific? I will show you an example (assuming that the hibernate configuration is correct, to keep the code concise, do not introduce the package and handle any exceptions)
Sessionfactory Sf = new configuration (). Configure (). buildsessionfactory ();
Session S = SF. opensession ();
Cat cat = new CAT ();
Transaction TRAN = S. begintransaction (); (1)
S. Save (CAT); (2) (update Delete can also be used here)
S. evict (CAT); (3)
Tran. Commit (); (4)
S. Close (); (5)
This is a typical error that causes this exception. I encountered this exception at the time. When I checked the code, I didn't even feel a problem with this code. I took it for granted that I started a transaction on the session and saved the object to the database through the session, it is a normal process to detach this object from the session and commit the transaction. If this is normal, the problem must be elsewhere.
The problem is exactly here. My thoughts may not be wrong, but the viewpoint drawn from a wrong argument will never be correct. I always thought that I was directly operating on the database. I forgot a hibernate between me and the database. While hibernate provides persistence services for us, it also changes the way we operate databases. This method is different from our direct database operations, it is because we do not have a general understanding of this method that our applications do not get the expected results.
What is the difference between the persistence mechanism of hibernate? Simply put, Hibernate implements a cache zone on the database layer. when an object is saved or updated, Hibernate does not actually write the object into the database, instead, you only register the data in the cache based on the application's behavior. You only need to flush the cached data into the database to execute all the previously registered behaviors.
In the actual execution process, each session maintains all objects associated with the session and operations performed by the application on these objects through several mappings and sets, entityentries (Session ing of objects associated with the session), insertions (all insert operation sets), and deletions (delete operation set) are related to this discussion), updates (update operation set ). Next I will explain how hibernate works in the first example.
(1) generate a transaction object and mark the current session as a transaction (Note: database-level transactions are not started at this time ).
(2) The application uses S. save to save the cat object. At this time, the session puts the cat object into entityentries to mark that cat has been associated with the current session. Because the application saves the cat object, the session also registers the insert behavior of the application in insertions (behavior includes Object Reference, Object ID, session, persistent processing class ).
(3) S. evict (CAT) detaches the cat object from the s session. In this case, s removes the cat object from entityentries.
(4) When a transaction is committed, all the caches need to be flushed into the database. The session starts a transaction and runs the insert, update ,......, The delete operation is submitted in the order of all previously registered operations (Note: The update operation will be executed only after all insert operations are completed, and the special processing here may make a mess of your program, to control the execution sequence of operations, be good at using flush). Now cat is not in entityentries, but it is enough to access insertions only when executing the insert action, so there will be no exceptions at this time. The exception occurs when the session is notified that the object has been inserted. In this step, set the existsindatabase flag of CAT in entityentries to true because cat does not exist in entityentries, at this time, Hibernate considers that insertions and entityentries may cause non-synchronization due to thread security issues (I do not know whether the hibernate developers consider the processing methods in the example. If not, this may be a bug), so a net. SF. hibernate. assertionfailure is thrown and the program is terminated.
I think now we should understand where the program in the example is wrong. save will be executed immediately, and the cat object is too early to be detached from the session, resulting in the insertions of the session and the contents in entityentries are not synchronized. Therefore, when doing such operations, we must know when hibernate will flush data into the database, and do not detach the operated objects from the session before flush.
The solution to this error is that we can insert a s between (2) and (3. flush () forces the session to flush the cached data into the database (at this time, Hibernate starts the transaction in advance, and registers the insert statement of the Save registration in (2) in the database transaction, and clear all operation sets). In this way, the insertions set is empty when (4) the transaction is committed. Even if we detach cat, there will be no exception.
The previous section briefly introduced the flush mechanism of hibernate, the possible impact on our programs, and the corresponding solutions, the cache mechanism of hibernate will also bring unexpected effects to our programs in other aspects. See the following example:
(Name is the primary key of the cat table)
Cat cat = new CAT ();
Cat. setname ("Tom ");
S. Save (CAT );
Cat. setname ("Mary ");
S. Update (CAT); (6)
Cat littlecat = new CAT ();
Littlecat. setname ("Tom ");
S. Save (littlecat );
S. Flush ();
What does this example look like? It is estimated that most people who do not understand the hibernate cache mechanism will say that there is no problem, but it cannot run normally according to our ideas. Primary Key conflicts may occur during the flush process. You may want to ask: "Not changed cat before save (littlecat. has the name been updated? Why is there a primary key conflict ?" The reason for this is the cache flushing sequence I mentioned in the first case. hibernate adopts insert, update ,......, In the delete order, submit all registration operations, so your S. although Update (CAT) appears in the program in S. before save (littlecat), but during the flush process, all the save will be executed before update, which causes a primary key conflict.
The change method in this example is to add S. Flush () after (6) to force the session to update the cat name before saving littlecat. In this way, only the registration action S. Save (littlecat) will be executed during the second flush, so that there will be no primary key conflict.
Let's look at another example (a strange example, but it can be used to explain the problem)
Cat cat = new CAT ();
Cat. setname ("Tom ");
S. Save (CAT); (7)
S. Delete (CAT); (8)
Cat. ID = NULL; (9)
S. Save (CAT); (10)
S. Flush ();
In this example, an exception net. SF. hibernate. hibernateexception: identifier of an instance of cat altered from 8b818e920a86f0000010a86f03a9d0001 to null will occur during the runtime.
The example here also has a cache problem, but the reason is slightly different:
(7) and (2) are processed in the same way.
(8) The session registers the delete action in deletions and updates the registration status of the object in entityentries to deleted.
(9) The Cat Class Identifier Field is ID. If it is set to null, the ID can be re-allocated and saved to the database.
(10) At this time, the session will first check whether the cat object has been associated with the session in entityentries, because Cat only changes the attribute value and the reference has not changed, therefore, the registered object in the deleted status will be obtained. Because the object to be saved for the second time has been deleted in the current session, save forces the session to flush the cache before continuing. In the flush process, you must first execute the initial save action, in this save, check whether the ID of the cat object is the same as that of the original action. Unfortunately, the cat ID is assigned null, an exception is thrown, and the program is terminated, in the future development process, we should try not to change the ID of the object that has been operated before flush ).
Errors in this example are also caused by delayed cache updates (of course, they are also related to the informal use of hibernate). There are two solutions:
1. flush after (8). This ensures that cat is saved as a brand new object in (10.
2. Delete (9), so that the forced flush caused by the second save can be executed normally. Insert the cat object in the database and delete it, then, save the second time and re-insert the cat object. At this time, the cat ID is still consistent with the previous one.
These two methods can be used according to different needs, I only hope that I can help you in application development. If not, I hope you can correct them.
In general, due to the flush Processing Mechanism of hibernate, we need to consider changes in the database operation sequence and whether the delayed flush has an impact on the program results in some complicated object update and Storage Processes. If there is indeed an impact, you can add flush to the position where you need to maintain this operation order to force hibernate to flush the operations recorded in the cache into the database, which may not look very beautiful, but it is effective.