Transactions are the guarantee of the atomicity of logic, and by using transaction control, it is possible to avoid problems such as dirty data caused by logical processing failure.
The two most important features of a transaction are the level of communication and the data isolation levels of the transaction. The propagation level defines the scope of control of the transaction, and the transaction isolation level defines the scope of the transaction's control over the database read and write.
The following are the 7 propagation levels of a transaction:
1)propagation_required, the default spring transaction propagation level, which is characterized by the addition of transactions to the transaction if a transaction already exists in the context, and the new transaction execution if no transaction exists in the current context. So this level is usually sufficient to handle most business scenarios.
2)Propagation_supports, literally knowing, supports, supported, that the propagation level is characterized by the support of transaction join transactions if there is a transaction in the context, and non-transactional execution if there is no transaction. So, not all of the packages in the Transactiontemplate.execute code will have transactional support. This is often used to deal with non-core business logic operations that are not atomic in nature. Fewer scenarios.
3)propagation_mandatory, a transaction must exist in the context of the transaction requirement in this level, or an exception will be thrown! Configuring the propagation level of this mode is a guarantee of effective control context calling code omission to add transaction control. For example, a piece of code can not be called to execute alone, but once it is called, it must have the situation of the transaction to use this propagation level.
4)propagation_requires_new, you can literally know, new, each time you want a transaction, the propagation level is characterized by a new transaction being created each time, and the transaction in the context is suspended, and the context transaction is resumed after the current new transaction is completed.
This is a very useful level of communication, to give a scenario: now there is a send 100 red envelopes operation, before sending, to do some system initialization, verification, data logging operations, and then send 100 red envelopes, and then record the sending log, send log request 100% Accurate, if the log is inaccurate, Then the entire parent transaction logic needs to be rolled back.
How do you deal with your entire business needs? It is through this propagation_requires_new level of transaction propagation control can be done. A child transaction that sends a red envelope does not directly affect the commit and rollback of the parent transaction.
5)propagation_not_supported, this can also be literally known, not supported, is not supported, the current level is characterized by the existence of transactions in the context, the transaction is suspended, the execution of the current logic, the end of the transaction to restore the context.
What are the benefits of this level? can help you to minimize the likelihood of a transaction. We know that the larger a transaction is, the more risk it has. Therefore, in the process of dealing with transactions, to ensure that the scope as narrow as possible. A piece of code, for example, must be called every time a logical operation, such as a non-core business logic operation that loops 1000 times. Such code, if wrapped in a transaction, is bound to cause the transaction to be too large, resulting in some difficult to consider well-rounded exceptions. So the level of communication at this level of the transaction comes in handy. Use the current level of the transaction template to pick it up.
6)Propagation_never, the transaction is more stringent, the above transaction propagation level is just not supported, there is a transaction suspended, and the Propagation_never propagation level requires that the context of the transaction cannot exist, once a transaction, throw runtime exception, Force stop execution! At this level, life has a grudge against business.
7)propagation_nested, you can literally know, nested, nested-level transactions. The propagation level feature is that if a transaction exists in the context, the nested transaction executes, and if there is no transaction, the transaction is created.
So what is a nested transaction? Many people do not understand, I have read some of the blog, are some understanding deviation.
Nesting is a child transaction that is executed in a parent transaction, a child transaction is part of a parent transaction, a rollback point is established by the parent transaction before the child transaction is entered, called Save Point, and then the child transaction is executed, and the execution of the child transaction is considered part of the parent transaction, and the child transaction execution ends and the parent transaction resumes execution. The point is that save points. See a few questions to understand:
What happens if a child transaction is rolled back?
The parent transaction rolls back to the save point that was established before entering the child transaction, and then tries other transactions or other business logic, and the actions before the parent transaction are not affected and are not automatically rolled back.
what happens if the parent transaction is rolled back?
The parent transaction is rolled back, and the child transaction is rolled back! Why, because the child transaction is not committed until the end of the parent transaction, we say that the child transaction is part of the parent transaction, and that is the truth. So:
The submission of a transaction, what is the situation?
is the parent transaction committed first, then the child transaction commits, or the child transaction is committed first, and the parent transaction commits again? The answer is the second case, or the sentence, the child transaction is part of the parent transaction and is submitted uniformly by the parent transaction.
Now you can feel the "nesting", is that a little bit of meaning?
These are the 7 levels of communication for a transaction, and in everyday applications, it can usually meet a variety of business needs, but in addition to the level of propagation, in the process of reading a database, if two transactions are executed concurrently, how is the data between each other affected?
This requires an understanding of another feature of the transaction: the data isolation level
data Isolation LevelDivided into four different types:
1.Serializable: The most stringent level, the transaction serial execution, the resource consumes the most;
2.Repeatable READ: Guarantees that a transaction does not modify data that has been read by another transaction but not committed (rolled back). "Dirty reads" and "non-repeatable reads" are avoided, but more performance losses are incurred.
3.READ COMMITTED: The default transaction level for most mainstream databases ensures that one transaction does not read to another data that has been modified but not committed by a parallel transaction, avoiding "dirty reads". This level applies to most systems.
4.Read Uncommitted: Ensures that no illegal data is read during the read process.
The above explanation is actually a bit of a mouthful in each definition, which involves several terms: dirty reading, non-repeatable reading, and Phantom reading.
Here's an explanation:
Dirty read: The so-called dirty read, is actually read the other transaction rollback before the dirty data. For example, transaction B modifies the data x during execution, transaction a reads x before committing, and transaction B rolls back, so that transaction a becomes dirty read.
Non-repeatable READ: The literal meaning of non-repeatable reading is already very clear, such as transaction a first read a piece of data, and then execute the logic, transaction B will change this data, and then transaction a again read, found that the data does not match, is so-called non-repeatable read.
Magic reading: Small when the number of fingers, the first number 20, the second number is 11, how to do? You have a hallucination?
The same is true for phantom reading, where transaction a first gets 10 data based on the condition index, and then transaction b changes the database one data, which results in the same search condition as transaction A, so that transaction a searches again for 11 data, resulting in a phantom reading.
A Control relationship table:
Dirty reads non-repeatable reads Phantom reads
Serializable not going to be
Repeatable READ will not be
READ COMMITTED will not be
Read UNCOMMITTED will be
So the safest is the serializable, but the accompanying is also a high performance overhead.
In addition, two properties commonly used by transactions: ReadOnly and timeout
One is to set the transaction to read-only to improve performance.
The other is to set the time-out for transactions, which is generally used to prevent large transactions from occurring. Or that sentence, the business should be as small as possible!
Finally, a question is introduced:
There are 20 conditions that a logical operation needs to check, can you put the checked content out of the transaction in order to reduce the transaction?
Many systems start a transaction in the inside of the DAO, and then perform the operation, either at the end of the commit or rollback. This involves the problem of code design. Smaller systems can be used in this way, but in some larger systems,
In the more complex logic system, it is bound to embed too much business logic into DAO, which leads to the decrease of the reusability of DAO. So this is not a good practice.
To answer the question: Can you put some business logic checks out of the transaction in order to shrink the transaction? The answer is: for the core business check logic, can not be placed outside the transaction, and must be distributed under the concurrency control!
Once a check is made outside of a transaction, it is bound to cause the data that transaction A has checked to be modified by transaction B, resulting in a futile transaction A and concurrency problems that directly lead to business control failure.
Therefore, in the distributed high concurrency environment, the locking mechanism should be used for checking the core business logic.
For example, transaction opening needs to read a piece of data to verify, and then the logical operation needs to modify this data, and finally commit.
Such a process, if the read and verify the code is placed outside the transaction, then the read data is very likely to have been modified by other transactions, the current transaction once committed, will again overwrite the data of other transactions, resulting in data anomalies.
So when entering the current transaction, this data must be locked, using for update is a good control in the distributed environment.
A good practice is to use programmatic transactions rather than life-style, especially in larger-scale projects. For the configuration of the transaction, in the case of very large code, it will be a torment, and the human flesh of the way, absolutely cannot avoid this problem.
Keep DAO in the most basic operation for a table, and then the processing of the business logic is placed in the manager and service, while using programmatic transactions to control the transaction scope more precisely.
In particular, it is important to note that in cases where an exception may be thrown in a transaction, the catch should be cautious and not casually catch Exception cause the exception of the transaction to be eaten and not be rolled back properly.
Spring Configures declarative transactions:
* Configuration Sessionfactory
* Configure transaction Manager
* Propagation Characteristics of transactions
* Those classes those methods use the transaction
Writing business logic methods
* Inherit Hibernatedaosupport class, use Hibernatetemplate to persist, Hibernatetemplate is
The lightweight package for Hibernate session
* The run-time exception is not rolled back by default (including inheriting the RuntimeException subclass), and normal exceptions are not rolled
* When writing a business logic method, it is best to throw an exception up and down in the presentation layer (Struts) processing
* About transaction boundary settings, usually set to the business layer, do not add to DAO
<!--configuration Sessionfactory--
<bean id= "Sessionfactory" class= "Org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
<property name= "Configlocation" >
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!--configuration Transaction Manager-
<bean id= "TransactionManager" class= "Org.springframework.orm.hibernate3.HibernateTransactionManager" >
<property name= "Sessionfactory" ref= "Sessionfactory"/>
</bean>
<!--transaction propagation characteristics--
<tx:advice id= "Txadvice" transaction-manager= "TransactionManager" >
<tx:attributes>
<tx:method name= "add*" propagation= "REQUIRED"/>
<tx:method name= "del*" propagation= "REQUIRED"/>
<tx:method name= "modify*" propagation= "REQUIRED"/>
<tx:method name= "*" propagation= "REQUIRED" read-only= "true"/>
</tx:attributes>
</tx:advice>
<!--which classes of which methods use transactions--
<aop:config>
<aop:pointcut expression= "Execution (* com.service.*.* (..))" id= "TRANSACTIONPC"/>
<aop:advisor advice-ref= "Txadvice" pointcut-ref= "TRANSACTIONPC"/>
</aop:config>
<!--general IOC injection--
<bean id= "Usermanager" class= "Com.service.UserManagerImpl" >
<property name= "Logmanager" ref= "Logmanager"/>
<property name= "Sessionfactory" ref= "Sessionfactory"/>
</bean>
<bean id= "Logmanager" class= "Com.service.LogManagerImpl" >
<property name= "Sessionfactory" ref= "Sessionfactory"/>
</bean>
Spring transaction propagation and isolation levels