Annulation des transactions printanières
1. Problèmes rencontrés
Lorsque nous avons plusieurs opérations de sauvegarde de base de données dans une seule méthode, une erreur se produit dans l'opération de base de données intermédiaire. Le pseudo-code est le suivant :
public method() { Dao1.save(Person1); Dao1.save(Person2); Dao1.save(Person2);//假如这句发生了错误,前面的两个对象会被保存到数据库中 Dao1.save(Person2); }
Situation attendue : Toutes les opérations de sauvegarde de la base de données avant que l'erreur ne se produise sont annulées, c'est-à-dire qu'aucune sauvegarde n'est effectuée
Situation normale : La base de données précédente L'opération sera exécutée et toutes les opérations de sauvegarde de données commençant et après une erreur d'opération de base de données échoueront. Cela ne devrait pas être le résultat que nous souhaitons.
Lorsque nous rencontrons cette situation, nous pouvons utiliser les transactions Spring pour résoudre ce problème.
2. Quelques connaissances de base sur les exceptions
1) Architecture des exceptions
Structure d'héritage des exceptions : Throwable est la classe de base, Error et Exception héritent de Throwable, RuntimeException et IOException, etc. .Hérite de l'exception. Error et RuntimeException et leurs sous-classes deviennent des exceptions non vérifiées (non vérifiées), et les autres exceptions deviennent des exceptions vérifiées (cochées).
2) Exception d'erreur
L'erreur indique qu'une erreur très grave et irrécupérable s'est produite lors de l'exécution du programme. Dans ce cas, l'application ne peut que. Abandonnez l'opération, par exemple, une erreur se produit dans la machine virtuelle JAVA. L'erreur est une exception non vérifiée. Le compilateur ne vérifie pas si l'erreur a été gérée et il n'est pas nécessaire d'intercepter les exceptions de type Erreur dans le programme. Dans des circonstances normales, les exceptions de type Error ne doivent pas être générées dans les programmes.
3) RuntimeException
L'exception inclut RuntimeException et d'autres exceptions non-RuntimeException.
RuntimeException est une exception non vérifiée, ce qui signifie que le compilateur ne vérifiera pas si le programme gère RuntimeException. Il n'est pas nécessaire d'intercepter les exceptions de type RuntimException dans le programme, et il n'est pas nécessaire de déclarer la classe RuntimeException dans le fichier. corps de la méthode. Lorsqu'une RuntimeException se produit, cela signifie qu'une erreur de programmation s'est produite dans le programme. L'erreur doit donc être trouvée et le programme modifié au lieu d'intercepter la RuntimeException.
4) Exception vérifiée
Exception vérifiée, qui est également l'exception la plus couramment utilisée en programmation. Toutes les exceptions qui héritent d'une exception et ne sont pas des exceptions RuntimeException sont des exceptions vérifiées. et ClassNotFoundException. Le langage JAVA stipule que l'exception vérifiée doit être traitée. Le compilateur vérifiera cela et déclarera une exception vérifiée dans le corps de la méthode ou utilisera une instruction catch pour capturer l'exception vérifiée pour le traitement.
3. Exemple
La configuration de transaction utilisée ici est la suivante :
<!-- Jpa 事务配置 --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
Dans le fichier de configuration Spring, si le paramètre defaultAutoCommit de la source de données est Si c'est True, alors si la méthode intercepte l'exception d'elle-même, la transaction ne sera pas annulée. Si l'exception n'est pas interceptée d'elle-même, la transaction sera annulée, comme dans l'exemple suivant <🎜. > Par exemple, il existe un tel enregistrement dans le fichier de configuration
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="xxx" value="xxx"/> <property name="xxx" value="xxx"/> .... <property name="defaultAutoCommit" value="true" /> </bean>
Situation 1 : Si elle n'est pas capturée manuellement dans le programme Exception
@Transactional(rollbackOn = { Exception.class }) public void test() throws Exception { doDbStuff1(); doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作 会回滚。 }
@Transactional(rollbackOn = { Exception.class }) public void test() { try { doDbStuff1(); doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作 不会回滚。 } catch (Exception e) { e.printStackTrace(); } }
Écrivez-le simplement comme ceci pour annuler manuellement la transaction :
@Transactional(rollbackOn = { Exception.class }) public void test() { try { doDbStuff1(); doDbStuff2(); } catch (Exception e) { e.printStackTrace(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//就是这一句了,加上之后,如果doDbStuff2()抛了异常, //doDbStuff1()是会回滚的 } }