I present to you the translation of the second chapter of the official documentation Hibernate .Article translation is relevant for the version Hibernate 4.2.19.FinalContent')
2.1. Transaction definition2.2. Physical transactions2.2.1. Physical Transactions - JDBC2.2.2. Physical Transactions - JTA2.2.3. Physical Transactions - CMT2.2.4. Physical Transactions - Other2.2.5. Physical Transactions - Legacy2.3. Hibernate transaction application2.4. Patterns and anti-transaction patterns2.4.1. Session-to-operation anti-pattern2.4.2. Session-to-request pattern2.4.3. Conversations (Conversations)2.5. Object identity2.6. General issues2.1. Transaction definition
It is important to understand that the term “transaction” has many meanings in relation to persistence and object-relational projection.
In most, but not all cases, the following definitions are appropriate.
- May be related to physical database transactions.
- May be related to the logical concept of “transaction”, as related to the context of persistence.
- May refer us to the concept of Unit-of-Work, as a well-defined architectural pattern.
ImportantThis documentation considers the logical and physical concepts of a transaction as one concept.
2.2. Physical transactions
Hibernate uses the JDBC API for persistence. In the Java world, there are two well-defined transaction mechanisms: JDBC and JTA directly. Hibernate supports both transaction integration mechanisms and allows applications to manage physical transactions.
The first concept in understanding Hibernate transaction support is the
org.hibernate.engine.transaction.spi.TransactionFactory interface, which provides two main functions:
- It allows Hibernate to understand the transaction semantics of the current environment. Are we working now in the environment of JTA? Is the physical transaction already active at this time, etc.
- It acts as a factory of org.hibernate.Transaction instances used by the application to manage and verify the status of transactions, org.hibernate.Transaction is Hibernate's logical transaction concept. JPA has a similar concept in the javax.persistence.EntityTransaction interface.
Importantjavax.persistence.EntityTransaction is available only when you use resource-local transactions. Hibernate provides access to org.hibernate.Transaction regardless of the environment.
org.hibernate.engine.transaction.spi.TransactionFactory is a standard Hibernate service. See Details in
section 7.5.16, “org.hibernate.engine.transaction.spi.TransactionFactory” .
2.2.1. Physical Transactions - JDBC
Transaction management using JDBC is achieved by the methods
java.sql.Connection.commit () and
java.sql.Connection.rollback () (JDBC does not define an explicit method for initiating a transaction). In Hibernate, this approach is represented by the class
org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory2.2.2. Physical Transactions - JTA
JTA-approach to transactions is achieved by the
javax.transaction.UserTransaction interface, obtained from the
org.hibernate.service.jta.platform.spi.JtaPlatform API. This approach is represented by the
org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory class
.See JTA Integration
Section 7.5.9, “org.hibernate.service.jta.platform.spi.JtaPlatform”2.2.3. Physical Transactions - CMT
Another JTA-based transaction approach uses the
javax.transaction.TransactionManager interface, obtained from the
org.hibernate.service.jta.platform.spi.JtaPlatform API. This approach is represented by the
org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory class. In the current environment of JEE CM, access to
javax.transaction.UserTransaction is closed.
ImportantThe term CMT is potentially misleading. The important part is that the physical JTA transactions are managed by some other means other than the Hibernate API.
See on JTA integration
section 7.5.9, “org.hibernate.service.jta.platform.spi.JtaPlatform” .
2.2.4. Physical Transactions - Other
It is also possible to connect a custom transaction management solution by implementing the
org.hibernate.engine.transaction.spi.TransactionFactory contract. The initiator of the default service has built-in support for recognizing custom solutions through
hibernate.transaction.factory_class , which may indicate:
- The org.hibernate.engine.transaction.spi.TransactionFactory instance.
- The name of the implementation class is org.hibernate.engine.transaction.spi.TransactionFactory . The implementation class must have a constructor with no arguments.
2.2.5. Physical Transactions - Legacy
Most of those classes mentioned above were migrated to new packages during development version 4.0. To help with upgrading to a new version, Hibernate will recognize obsolete names for a short period of time.
- org.hibernate.transaction.JDBCTransactionFactory maps to org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
- org.hibernate.transaction.JTATransactionFactory maps to org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory
- org.hibernate.transaction.CMTTransactionFactory maps to org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory
2.3. Hibernate transaction application
Hibernate uses JDBC connections and JTA resources directly, with no additional synchronization logic. It is important for you to become familiar with JDBC, ANSI SQL, and the specifics of transaction isolation in your DBMS.
Hibernate does not synchronize on objects in memory. The behavior determined by the isolation level of your DB transactions does not change when you use Hibernate. The
org.hibernate.Session object acts as a repeatable reads and cache requests that are limited to the limits of the transaction.
ImportantTo reduce blocking competition, transactions should be as short as possible. Long transactions make it difficult to scale your application to high loads. You do not need to keep transactions open while the end user is working; you need to open them after the user has finished working. This concept is also differently called transactional write-behind.
2.4. Patterns and anti-transaction patterns
2.4.1. Session-to-operation anti-pattern
This is an anti-pattern for opening and closing a
Session object for each operation to the database in one thread. It is also an anti-pattern in terms of database transactions. Group your calls into one scheduled sequence. Also, do not auto-commit transactions per SQL statement. Hibernate turns off, or expects the application server to turn off auto-commit mode immediately. Transactions to the database have never been optional. All communications with the database must be wrapped in a transaction. Avoid auto-commit when reading data, because quite rarely a lot of small transactions will work faster than one properly defined transaction. Moreover, such a multitude of transactions is difficult to maintain and expand.
ImportantThe use of autocommit does not necessarily lead to the use of database transactions for each expression. Instead, in autocommit mode, JDBC drivers simply make each call as part of an implicit transaction call. This is the same as if your application made a commit () transaction call after each JDBC call.
2.4.2. Session-to-request pattern
The most common transaction pattern. The term “request” here should be understood in the context of a system that responds to a series of requests from a user / client. Web applications are a prime example of such systems, but, of course, they are not the only ones. At the stage of starting the processing of a request, the application opens the
Session object, initiates a transaction, does all the related work with the data, completes the transaction and closes the
Session . The essence of the pattern is a one-to-one relationship between a transaction and a session.
As part of the pattern, there is a common technique for determining the current session to simplify the transfer of this
Session between application components. Hibernate provides support for this technique through the
getCurrentSession () method of the
SessionFactory class. The concept of a “current” session should have a scope that defines the boundaries in which the definition of “current” is true. This is the task of the
org.hibernate.context.spi.CurrentSessionContext contract. There are two reliably defined scopes:
- A JTA transaction that, through callback, can let Hibernate know when it has completed, which in turn provides the ability to terminate the current session. This strategy is represented by org.hibernate.context.internal.JTASessionContext - the implementation of the org.hibernate.context.spi.CurrentSessionContext contract. Using this implementation, the Session will be opened as soon as getCurrentSession () is called within the transaction.
- The request cycle itself. Org.hibernate.context.internal.ManagedSessionContext is best represented by the implementation of the org.hibernate.context.spi.CurrentSessionContext contract. There is an external component responsible for managing the life cycle and scope of the “current” session. At the stage of starting the scope, the bind () method is called on the ManagedSessionContext with the transfer of the link to the session. At the end, the unbind () method is called .
ImportantThe getCurrentSession () method has one nasty side in JTA. If you use it, the after_statement connection release mode will also be used by default. Due to limitations of JTA, Hibernate cannot automatically clean up any unclosed instance of ScrollableResults or Iterator returned by scroll () or iterate () . The release of DB cursors is done by calling ScrollableResults.close () or Hibernate.close (Iterator) explicitly from the finally section.
2.4.3. Dialogues
Session-to-request pattern is not the only unit of work design tool. Many business processes require a whole series of user interactions that alternate with access to the database. In web and enterprise applications, it is unacceptable for a database transaction to cover all user interaction. Consider the following example:
Procedure 2.1. Example of “long-playing” dialogue- The first screen of the dialog opens. The data shown to the user is loaded in a separate session session and database transaction. The user can modify any dialog fields.
- After five minutes of editing, the user uses the UI element to save. Changes are reflected in the database. The user also expects exclusive data access during the editing session.
Even though we have several cases of access to the database, from the user's point of view, this series of steps represents one unit of perfect work (Unit of Work). There are many ways to implement this in an application.
The first (naive) method is to keep
Session sessions and transactions open while the user is editing, using database synchronization mechanisms to provide exclusive user access to editable data, and prevent other users from accessing them, ensuring isolation and atomicity. This is an anti-pattern, since unnecessary synchronization is a bottleneck for performance problems arising in high-load applications.
A number of database transactions is used to implement a dialogue with the database. In this case, ensuring the isolation of business processes falls on the shoulders of the application. One conversation usually covers multiple transactions. Multiple database accesses can be atomic if only one transaction (usually the last one) writes to the database. All others only read the data. A typical implementation path is through the creation of a wizard-style dialog covering several steps of a request / response cycle. Hibernate includes some features that allow you to implement similar functionality.
- Automatic Versioning
Hibernate can perform concurrency control for you. It can automatically detect if third-party
update data while waiting user.
- Detached Objects
If you prefer to use the session-per-request template,
all downloaded instances will be disconnected while the user is waiting. Hibernate allows you to connect back
objects and save modifications. This pattern is called session-per-request-with-disconnected objects. Automatic versioning is used to isolate concurrently running queries.
- Extended session
Session Session can be disconnected from the underlying JDBC connection after the DB transaction is committed, and reconnected when a new client request arises. This pattern is called session-to-dialogue , which makes the reattachment of objects unnecessary. Automatic versioning is used to isolate parallel modifications, and the session cannot be flushed automatically, only explicitly.
Session-to-request-with-disconnected-objects and
session-to-dialogue have their pros and cons.
2.5. Object identity
An application can simultaneously access the same persistent state (a string in a database) in two different sessions. However, an instance of a persistent class is never split between two different sessions. Two different notions of identity take place and come into play: DB-identity and JVM-identity.
Example 2.1. DB identityfoo.getId().equals( bar.getId() )
Example 2.2. JVM Identity foo==bar
For objects attached to the same Session session, two identity concepts are equivalent, and JVM identity is guaranteed by the Hibernate database identity. An application can simultaneously access a business object with the same database identity in two different sessions; meanwhile, it will be represented by two different instances of Java objects, in terms of JVM identity. Conflict resolution is performed by optimistic strategy and automatic versioning during flush / commit.
This approach places the responsibility for managing concurrency on Hibernate and the database. It also provides better scalability, since expensive locks are not needed to guarantee identity in a single-threaded unit of work (single-threaded unit of work). There is no need for the application to synchronize on any business object while it is running in one thread. Although not recommended, within an Session session, an application can safely use the == operator to compare objects.
However, an application using the == operator outside a session can introduce some problems. If you add two detached instances of an object to the same Set, they will probably have the same database identity, that is, they represent the same row in the table. It is not at all guaranteed that they will have the same JVM identity, being able to be detached. Override the equals () and hashCode () methods in persistent classes so that they have their own definition of object equivalence. Do not use the identity database to implement the equality test. Instead, use a business key that is a combination of unique, immutable attributes. The database identifier may change if the object changes from the transient state to the persistent state. If a transient instance is found with the detached instance in the same Set'e - changing the hashcode will violate the Set'a contract. Attributes for a business key may be less robust than basic keys. You only need to guarantee stability as long as the objects are in the same Set. This is not a Hibernate problem, as it relates to the implementation of object identity and equivalence in Java.
2.6. General issues
Both
session-per-session-user and
session-per-application anti-patterns are susceptible to the following issues. Some of these problems may also occur in the recommended patterns, so first make sure that you understand the implications before making any design decisions:
- Session Session is not thread safe. Entities working in parallel, such as HTTP requests, session bins, or Swing workers, will lead to race conditions if a session is divided between threads. If you store your Hibernate session in your javax.servlet.http.HttpSession (discussed later), you need to consider the problem of synchronized access to your HttpSession ; otherwise, a user clicking the Refresh button too quickly will use the same session in two threads running in parallel.
- The exception thrown by Hibernate means that you have to rollback your transaction and close the session immediately (discussed in more detail in the following chapters). If your session is restricted by the application, you must stop the application. Rolling back a transaction does not roll back your business objects to the state they were at when the transaction started. This means that the state in the database and the state of the objects have been out of sync. Usually, this is not a problem because exceptions are not recoverable, and you still need to start over after a rollback.
- Session caches each object that is in the persistent state (that is, it is monitored and checked for changes by Hibernate). If you leave it for a long time, or simply load too much data, it will grow many times, until you get an OutOfMemoryException . There is a solution to call clear () and evict () to manage the session session cache, but you should consider alternative ways of handling large amounts of data, such as stored procedures. Java is not a suitable tool for this kind of operation. Some solutions are shown in Chapter 4, Batch Processing . A session that remains open during the user's session also means a high probability of the appearance of “stale” data.