Before talking about Spring transaction management, let’s think about how we perform data operations in Hibernate when we don’t use Spring. In Hibernate, we must first start the transaction, then perform data operations, then submit the transaction, and close the transaction. The reason we do this is because Hibernate's default transaction automatic commit is false, which requires us to manually submit the transaction. If you don't want to manually submit the transaction every time, you can set it to automatically commit the transaction in my file hibernate.cfg.xml:
xml code
<property name="defaultAutoCommit"> <value>false</value> </property>
Even though we set its transaction commit method to automatic, it can perform data operations, this does not meet our actual business needs, because sometimes after I save one data, I hope it can continue to save another data. I hope to commit the transaction together after saving two or more data. In this way, even if there is an error, we can roll back and secure the consistency of the data. Either success or failure. At this time, we cannot automatically commit the transaction after saving one data, because they are not in the same transaction, and we cannot guarantee the consistency of the data. So at this time we need to manually configure our transactions, which requires the use of the transaction management mechanism provided by Spring for Hibernate. The transaction management provided by Spring can be divided into two categories: programmatic and declarative. Programming is actually controlled in the code. Just like Hibernate operates data, it starts transactions and submits transactions. This method has certain limitations, so we generally use declarative to configure our transactions.
Declarative transaction configuration is mainly divided into the following steps:
1. Declarative transaction configuration
(1) Configure the transaction manager;
(2) The propagation characteristics of the transaction;
(3) Those classes and methods use transactions.
<!-- Configure the sessionFactory that the transaction manager specifies its function and hand over the transaction to Spring for processing --> <bean id="transactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> <!-- Configure the propagation characteristics of transactions --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- Which methods of those classes participate in transactions--> <aop:config> <aop:pointcut id="allServiceMethod" expression="execution(* com.coe.service.*.*(..))"/> <aop:advisor pointcut-ref="allServiceMethod" advice-ref="txAdvice"/> </aop:config>
When configuring transactions, we usually set the transaction boundary to the service layer, that is, your business logic layer, because we often complete some of our columns of data operations in our business logic layer. If placed in the Dao data layer, the granularity is too small. In addition, if we configure transactions in the business logic layer, it will also be beneficial to our secondary cache, which you will find in the future when you actually operate it.
2. Write business logic methods
At this time, we can use the data operation methods provided in HibernateTemplate to write our business logic methods in our business logic layer. Of course, our method must be the same as configured in our transaction configuration, using save, delete, update, and get as the beginning of our method. It should be noted that by default, the runtime exception will only roll back (including inheriting the RuntimeException subclass), and ordinary exceptions will not roll.
Finally, let’s summarize the several propagation characteristics of transactions:
1. PROPAGATION_REQUIRED: If a transaction exists, the current transaction is supported. If there is no transaction, it will be enabled;
2. PROPAGATION_SUPPORTS: If a transaction exists, the current transaction is supported. If there is no transaction, the execution of non-transactions;
3. PROPAGATION_MANDATORY: If a transaction already exists, the current transaction is supported. If there is no active transaction, an exception is thrown;
4. PROPAGATION_REQUIRES_NEW: Always open a new transaction. If a transaction already exists, the existing transaction is suspended;
5. PROPAGATION_NOT_SUPPORTED: Always execute non-transactionally and suspend any existing transaction;
6. PROPAGATION_NEVER: Always executed non-transactionally, if an active transaction exists, an exception is thrown;
7. PROPAGATION_NESTED: If an active transaction exists, it runs in a nested transaction. If there is no active transaction, execute it according to the TransactionDefinition.PROPAGATION_REQUIRED property.
Through this article, I hope it can help you understand the integrated transaction management of Spring and Hibernate. Thank you for your support for this website!