Hibernate3.6 documents notes on transactions and concurrency policies

Source: Internet
Author: User

Hibernate3.6 documents notes on transactions and concurrency policies

 

Possible life cycles of hibernate sessions: 1. Operation (execution of an SQL statement) 2. Request 3. Open Session in view (derived from request) 4. Conversion

Work Unit: composed of multiple operations
Session-per-operation (operation is an SQL statement executed by a session). This also means that after a single SQL statement is sent in an application, the auto-commit mode is invalid. Database transactions are by no means dispensable. any communication with the database must be performed in a transaction, whether you are reading or writing data. To read data, avoid auto-commit because many small transactions have poor performance than a clearly defined unit of work. The session-per-request mode is a useful concept used to design operation units.

In multi-user client/server applications, the most common mode is to request a session (Session-per-request ). (A session executes Multiple SQL statements throughout the request .) In this mode, requests from the client are sent to the server (where the Hibernate Persistence Layer runs), and a new hibernate session is opened, and execute all the database operations in this operation unit. Once the operation is completed (and the response to the client is ready), the session is synchronized and then closed.
You can also use a single database transaction to process client requests (one session, one transaction executes Multiple SQL statements), start the transaction after you open the session, and submit the transaction before you close the session. The relationship between sessions and requests is one-to-one, which is great for most applications.
How to Implement session-per-Request: servletfilter, proxy/interception container

Topic triggered by session-per-Request: Open Session in view
It is convenient to extend the session and Database Transaction boundary to "after the presentation layer is rendered. If you implement your own interceptor, it is very easy to extend the transaction boundary to the display layer after rendering. However, if you rely on the EJB of [[container management transactions], this is not easy, because the transaction will end after the return of the EJB method, that is before the rendering of any presentation layer starts.

In a business transaction scenario, a conversion consists of multiple requests. Each request corresponds to a transaction. Hibernate allows only one session to be used in the entire conversion process. This method is also called extended (or long) session.
The Hibernate session can be disconnected from the underlying JDBC connection after the database transaction is committed. When a new client request arrives, it reconnects to the underlying JDBC connection. This mode is called session-per-conversation. In this case, unnecessary session and JDBC connection can be reassociated. Automatic version is used to isolate concurrent modifications. sessions generally do not allow automatic flush, but explicitly flush.

 

Typical persistent sessions (business transactions) scenarios:
*
On the first screen of the interface, open the dialog box. The data you see is loaded by a specific session and Database Transaction (load. You can modify the data objects in the dialog box at will.
*
Five minutes later, the user clicks "save" and expects the modifications to be made to be persistent. At the same time, the user [also expects that he is the only person Who modifies the information and will not conflict with the changes].
From the user's point of view, we call this operation unit conversation or application transaction)

For application transactions and system transactions, concurrent updates may occur in two environments: 1. for a transaction cycle (or a request cycle), 2: Cross-transaction cycle (can be understood as a session cycle ), it includes the time for users to think.
In the past, I did not understand the nature of transaction isolation. I thought that only the scenario of long sessions is the scenario of concurrent modification in CMM. In fact, CCM does not involve long sessions. It only deals with problems caused by modifying the same data for other concurrent transactions in a transaction cycle.
For 1, The adopt scheme is optimistic lock or pessimistic lock. The lock cost is compared with the business cost.
For 2, optimistic offline locks and pessimistic offline locks are adopted.

Solution of hibernate for business transactions:
The first naive approach is to keep session and database transactions open while the user is thinking, and keep the database locked to prevent concurrent modifications, this ensures the database transaction isolation level and atomic operations. This is of course an anti-pattern, Because lock contention will make the application unable to expand the number of concurrent users. (It seems that hibernate strongly opposes this long transaction)

Obviously, we must use multiple database transactions to implement this conversation. In this example, maintaining transaction isolation for business processing becomes part of the responsibility at the application layer. A conversation typically spans multiple database transactions. If only one database transaction (the last transaction) stores the updated data, while all other transactions only read data (for example, in a wizard-Style dialog box that spans multiple request/response cycles), application transactions guarantee their atomicity. This method is easier to implement than it sounds, especially when you use the following features of hibernate:
*
Automatic versioning: hibernate can automatically control optimistic concurrency. If concurrent modifications occur during users' thinking, Hibernate can automatically detect the changes. Generally, we only check when the conversation ends (that is, when the last transaction of the system transaction set contained in the business transaction is committed. The check principle is also version = version + 1 where version = ?, Only the SQL structure is automatically generated by hibernate, and versionized update statements are the core of optimistic offline lock implementation ).
*
Detached objects: If you decide to use the session-per-request mode discussed earlier, all loaded instances are in the disconnections from session during users' thinking. Hibernate allows you to reassociate an object that is detached from a session to a session and make modifications persistent. This mode is called session-per-request-with-detached-objects. Automatic Versioning is used to isolate concurrent modifications. (Update (detach object) is one of the implementation methods of optimistic offline locks. The above automatic versioning features should be used for generating statements. If JDBC is used, the version number is saved in the HTTP session. This method is also commonly used. The detach object is usually stored in HTTP sesson, in this way, when the last update request reaches, the user can conveniently obtain the update)
*
Extended (or long) Session: The Hibernate session can be disconnected from the underlying JDBC connection after the database transaction is committed. When a new client request arrives, it reconnects to the underlying JDBC connection. This mode is called session-per-conversation. In this case, unnecessary session and JDBC connection can be reassociated. Automatic version is used to isolate concurrent modifications. sessions generally do not allow automatic flush, but explicitly flush. (My personal understanding: This method should not close the session every request, the detach object does not need to be copied to the HTTP session as the session-per-Request Method for the session corresponding to the next request)
Session-per-request-with-detached-objects and session-per-conversation have their respective advantages and disadvantages. We will discuss the Optimistic Concurrency Control Section later in this chapter.

 

Object ID:

Applications may concurrently access the same persistent state in two different sessions. However, an instance of a persistence class cannot be shared between the two sessions. Therefore, there are two different semantic identities:
Database ID
Foo. GETID (). Equals (bar. GETID ())
JVM ID
Foo = bar
For objects associated with a specific session (that is, within the range of a single session), the semantics of the two identifiers is equivalent, the jvm id corresponding to the Database ID is [[[hibernate] (: it is estimated that hibernate will think that if Foo and bar are in the same session, foo is used. GETID (). equals (Bar. GETID () to determine whether it is equivalent ). However, when an application accesses a business object instance with the same persistent identifier concurrently in two different sessions, the two instances of this business object are actually different (from JVM recognition ). This conflict can be solved through automatic versioning and Optimistic Locking during synchronization and submission. (: When different sessions hold Foo and bar respectively, they should be two different new instances. From the JVM perspective, of course, they are not equivalent. However, their destinations are all records in the database. Concurrent updates may occur when the request is submitted at the same time. This is also to prepare for describing optimistic offline locks .)

In this way, the headache of concurrency is left to hibernate and the database. Because in a single thread, Object Recognition in the operation unit does not require expensive locking or synchronization in other sense, therefore, it can provide the best scalability at the same time. As long as only one session is held in a single thread, the application does not need to synchronize any business objects. Within the range of sessions, applications can safely use = to compare objects. (: Foo and bar in the same session)

However, using = outside the session to compare objects may lead to unexpected results. (: Sessiona holds Foo and sessionb holds bar. When they are put into a set respectively, they actually correspond to a record, but they are placed twice because foo! = Bar, so you need to implement the custom equals/hashcode method) in some unpredictable scenarios. For example, if you put two unmanaged object instances in the same set, it may happen. The two object instances may have the same database identifier (that is, they represent the same row of data in the table). From the definition of the JVM identifier, hibernate cannot ensure that their JVM IDs are consistent. Developers must overwrite the equals () method and hashcode () method of the persistence class to implement custom object equality semantics. Warning do not use database identifiers to achieve equality of objects. The business key value should be used, which is composed of unique, usually unchanged attributes. When an instantaneous object is persisted, its database ID changes. If an instantaneous object (usually including a decentralized object instance) is put into a set, changing its hashcode will interrupt the relationship with this set. Although the business key value attributes are not as stable as the database primary key, you only need to ensure the stability of the object attributes in the same set. Go to the hibernate website for more detailed discussions on this issue. Please note that this is not a question about hibernate, but just about how to implement Java object identification and determination.

13.2 talked about some transaction knowledge in hibernate.

-----------------------------------------------

Hibernate implements optimistic offline locks

Hibernate is used, but does not use its reattach feature or extended session implementation. Instead, it uses the traditional optimistic offline lock implementation method, which is not recommended when hiberate is used, if JDBC is used, you can only use the traditional implementation method:

Traditional implementation method-application version check)

In codes that fail to fully utilize the hibernate function, a new session is required for every interaction with the database, and developers must re-load all persistent object instances from the database before displaying data. This method forces the application to implement Version checks on its own to ensure the isolation of conversational transactions, which is the most inefficient in terms of data access. This method is the most similar to entity EJB.

// Foo is an instance loaded by a previous session

Session = factory. opensession ();

Transaction T = session. begintransaction ();

Int oldversion = Foo. getversion ();

Session. Load (Foo, foo. getkey (); // load the current state

If (oldversion! = Foo. getversion () throw new staleobjectstateexception ();

Foo. setproperty ("bar ");

T. Commit ();

Session. Close ();

The version attribute uses <version> for ing. if the object is dirty data, Hibernate automatically adds the version number during synchronization.

Of course, if your application is in a low data concurrency environment and does not require version check, you can still use this method, but skip version check. In this case, the last commit wins is the default processing policy for your long conversation. Keep in mind that such policies may confuse the users of the application software, because they may encounter a situation where the update is lost but there is no error information, or the change conflict needs to be merged.

Obviously, manual version checks are only applicable to some application scenarios with very small software sizes and are not realistic for most application scenarios. In general, not only does a single object instance require version check, but the entire modified associated object graph also requires version check. As a standard design example, Hibernate provides automatic Version checks by extending the cycle of sessions or by taking off the management of object instances.

 

 

With hibernate, we recommend the following method: extend the session and automatically versioning of the cycle.

A single session instance and all its associated Persistent object instances are used for the entire conversation. This is called session-per-conversation. Hibernate checks the version of the object instance during synchronization. If concurrent modifications are detected, an exception is thrown. It is up to developers to determine whether to capture and handle this exception (the general choice is to provide users with a chance to merge changes or re-engage in business conversations without dirty data ).

When waiting for user interaction, the session disconnects the underlying JDBC connection. This method is the most efficient way for database access. The application does not need to care about version check or re-Association of the unmanaged object instance (: checkconcurrent and Upate (detachobject). In each database transaction, the application does not need to load the read object instance (checkconcurrent is not required, and reload instance is not required ).

// Foo is an instance loaded earlier by the old session

Transaction T = session. begintransaction (); // obtain a new JDBC connection, start transaction

Foo. setproperty ("bar ");

Session. Flush (); // only for last transaction in conversation

T. Commit (); // also return JDBC connection

Session. Close (); // only for last transaction in conversation

The Foo object knows in which session it is loaded. Starting a new database transaction in an old session will cause the session to obtain a new connection and resume the session function. Commit database transactions, disconnect the session from the JDBC connection, and return the connection to the connection pool (multiple system transactions in the business transaction, after each system transaction is committed, will return the connection pool ).

1. gyb: how to perform the force Update check:
After reconnecting, you must force a version check on the data you have not updated. You can use the lockmode parameter for [[all objects that may have been modified by other transactions. read to call the session. lock ()].

2. how to ensure that the last transaction sends "modifications to the entire session" to the database is a problem that I have never solved. I have simplified all business transactions into two system transactions, the first load and the second modify.
You do not need to lock any data you are updating. Generally, you will set flushmode. Never on the extended session. Therefore, [[only the last Database Transaction loop will actually send the changes in the entire dialog to the database]. Therefore, only the last database transaction will contain the flush () operation, and then close () the session after the entire session ends.

Gyb:
My question is that transactions are flushed during commit. If the first system transaction contains not only the load operation but also the update operation, will it cause flush as the first system transaction is committed? The answer is to trace the source code and find that the commit method will perform the flush operation unless sessoin is in flushmode. Never. Therefore, it should be clear that not all commit will perform the flush operation.

3. The session should be as small as possible like the htppsession.
If the session cannot be saved because it is too large during users' thinking, this mode is problematic. For example, an httpsession should be as small as possible.
Since the session is a level-1 cache and keeps all objects loaded, we should only use this policy in the case of a small number of requests/response. You should use only one session for a single conversation (avoid multiple sessions using the same session), because it will soon produce dirty data.

 

 

With hibernate, the recommended method 2 is deatched object and automatic versioning.

In this way, each interaction with persistent storage occurs in a new session. However, the same Persistent object instance can be reused in the interaction with the database multiple times. The application operates the status of the unmanaged object instance. The unmanaged object instance is initially loaded in another session and then calls the session. update (), session. saveorupdate (), or session. to re-associate the object instance.

// Foo is an instance loaded by a previous session

Foo. setproperty ("bar ");

Session = factory. opensession ();

Transaction T = session. begintransaction ();

Session. saveorupdate (FOO); // use Merge () If "foo" might have been loaded already

T. Commit ();

Session. Close ();

Hibernate checks the version of the object instance again during synchronization. If an update conflict occurs, an exception is thrown.

If you are sure that the object has not been modified (for example, the above Foo. setproperty ("bar") is a reattach operation in the second system transaction. It is strange to use update for version check, in this case, you can use another reattach method to lock. You can also call lock () to set the lockmode. read (bypasses all the caches and performs Version checks) to replace the update () operation.

Gyb: The above are two ways to implement optimistic offline locks when Hibernate is used as the persistent layer. On the premise of using hibernate, it is not recommended to use the traditional optimistic offline lock method (checkconcurrent + SQL with version updates-hibernate flushmode in session! = Never, you only need to commit () to synchronize object changes to the database, that is, to construct and execute SQL statements with version updates)

 

Use of optimistic offline locks for legacy systems:
Because the tables in the legacy system may not contain the version column, but cannot modify the table, you can use custom automatic version-based behavior:

For specific attributes and sets, you can set the value of the optimistic-lock optiing attribute to false to disable automatic addition of hibernate versions. In this case, if the attribute is dirty data, Hibernate will not add any version number.
The database schema of the legacy system is usually static and cannot be modified. Alternatively, other applications may access the same database and cannot know how to handle the version number or even the timestamp. In all the above scenarios, versioning cannot rely on a specific column in the database table. You can set optimistic-lock = "all" in <class> ing to check the version without ing versions or timestamp attributes, at this time, Hibernate compares the status of each field recorded in a row. Note that this method takes effect only when Hibernate is in the old or new State. That is to say, you must use a single session mode with a long life cycle, the session-per-request-with-detached-objects mode cannot be used.
In some cases, concurrent modifications are allowed as long as the changes are not staggered. When you set optimistic-lock = "dirty" in the <class> ing, Hibernate only compares dirty data fields during synchronization.

In all the above scenarios, whether it is to set a version/timestamp column or to compare all fields/dirty data fields, hibernate sends an update (with the corresponding where statement) SQL statement for each object to perform version check and data update. If you set the level of link persistence (transitive persistence) for the correlated object, Hibernate may execute unnecessary update statements. This is usually not a problem, but the trigger for on update ignition in the database may be triggered without any changes to the de-pipe object. Therefore, you can customize this line by setting select-before-update = "true" in the <class> ing, and force the hibernate select object instance to ensure that, the object was modified before the record was updated.

 

-----------------------------------------------

 

Pessimistic locking)
Users do not need to worry much about locking policies. Generally, you only need to specify the isolation level for the JDBC connection, and then let the database handle everything. However, advanced users sometimes want to apply a pessimistic lock to the transaction or re-apply the lock when a new transaction starts.

Hibernate always uses the database locking mechanism and never locks objects in the memory.
The lockmode class defines the different lock levels required by hibernate. A lock can be set through the following mechanism:
*
When hibernate updates or inserts a row of records, the lock level is automatically set to lockmode. Write.
*
When the user explicitly sends an SQL statement using the SQL format Select... for update supported by the database, the lock level is set to lockmode. Upgrade. (Gyb: When you want to achieve the effect of handwriting SQL: Select *** for update, you only need to set the locking mode to lockmode. Upgrade in hibernate. Hibernate is automatically translated into the corresponding SQL.
*
When you explicitly use the SQL statement Select... for update Nowait of the Oracle database, set lockmode. upgrade_nowait for the lock level. Gyb: Same as above
*
When hibernate reads data at the "repeatable" or "serialization" database isolation level, the lock mode is automatically set to lockmode. Read. This mode can also be explicitly specified by the user. Gyb: Same as above
*
Lockmode. None indicates no lock is required. At the end of transaction, all objects are switched to this mode. The object associated with the session is out of this mode by calling Update () or saveorupdate.

"Explicit user designation" (so "explicit designation" does not mean that the application directly uses SQL *** for update, but is implemented by calling the API provided by hibernate, hibernate will automatically translate into the corresponding SQL statement) can be expressed in one of the following ways:
*
Specify the lock mode when session. Load () is called)
*
Call session. Lock ().
*
Call query. setlockmode ().

If the session is called in upgrade or upgrade_nowait lock mode. load (), and the object to be read has not been loaded by the session, then the object uses select... SQL statements such as for update are loaded. If the load () method is called for an object and the object has been loaded in another locking mode with few restrictions, Hibernate calls the lock () method for the object.
If the specified locking mode is read, upgrade, or upgrade_nowait, session. Lock () checks the version number. (In upgrade or upgrade_nowait locking mode, execute SQL statements such as select... for update .)
If the database does not support the locking mode set by the user, Hibernate uses the appropriate alternative mode (instead of throwing an exception ). This ensures the portability of applications.

Gyb: The above are talking about hibernate how to achieve pessimistic lock, using JPA/hibernate to achieve a pessimistic offline lock reference: http://fangtianying.javaeye.com/blog/317044

 

-----------------------------------------------

 

Connection release

The old JDBC connection management (2.x) behavior of Hibernate is that the session obtains a connection when it is needed for the first time and will hold the connection until the session is closed. Hibernate introduces the concept of connection release to tell the session how to handle its JDBC connection. Note: The following discussion only applies to configuring connectionprovider to provide connections. The connections provided by the user are irrelevant to the discussion here. You can use the unused release mode using different enumerated values of org. hibernate. connectionreleasemode:
*
On_close: basically the old behavior mentioned above. The Hibernate session obtains the connection when the first JDBC operation is required, and then holds it until the session is closed.
*
After_transaction: Release the connection after org. hibernate. Transaction ends. (Extend session in optimistic offline locks implemented by hibernate needs this mode)
*
After_statement (also called active release): the connection is released after each statement is executed. However, if the statement leaves session-related resources, it will not be released. Currently, the only case is org. hibernate. scrollableresults.

The hibernate. Connection. release_mode configuration parameter specifies which release mode to use. Possible values include:
*
Auto (default): This option delegates the release mode to the org. hibernate. transaction. transactionfactory. getdefaultreleasemode () method. For jtatransactionfactory, it returns connectionreleasemode. after_statement; For jdbctransactionfactory, It is connectionreleasemode. after_transaction. This default behavior rarely needs to be modified, because improper configuration may lead to bugs or mislead user code.
*
On_close: Use connectionreleasemode. on_close. This method is intended for backward compatibility, but is not encouraged at all.
*
After_transaction: Use connectionreleasemode. after_transaction. This setting should not be used in the JTA environment. Note that when connectionreleasemode. after_transaction is used, if the session is in the auto-commit state, the connection will be released as after_statement.
*
After_statement: Use connectionreleasemode. after_statement. In addition, the onprovider configured is queried to see if it supports this setting (supportsaggressiverelease ()). If not, the release mode is set to connectionreleasemode. after_transaction. Only when you call connectionprovider each time. when getconnection () gets the underlying JDBC connection, you can be sure that this setting is secure when the same connection is obtained; or in the auto-commit environment, this is safe whether or not you get the same connection every time.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.