Gestion des transactions AOP Spring sous Hibernate

Gestion des transactions Spring AOP dans Hibernate

La gestion des transactions est nécessaire pour garantir l'intégrité et la cohérence des données dans la base de données. La technique AOP de Spring permet aux développeurs de gérer la déclaration déclarative de la transaction.

Voici un exemple pour montrer comment gérer la transaction Hibernate avec Spring AOP.

P.S Many Hibernate and Spring configuration files are hidden, only some important files are shown, if you want hand-on, download the full project at the end of the article.

1. Création de table

Des scripts de table MySQL, une table‘product et une tableproduct quantity on hand.

CREATE TABLE  `example`.`product` (
  `PRODUCT_ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `PRODUCT_CODE` varchar(20) NOT NULL,
  `PRODUCT_DESC` varchar(255) NOT NULL,
  PRIMARY KEY (`PRODUCT_ID`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE  `example`.`product_qoh` (
  `QOH_ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `PRODUCT_ID` bigint(20) unsigned NOT NULL,
  `QTY` int(10) unsigned NOT NULL,
  PRIMARY KEY (`QOH_ID`),
  KEY `FK_product_qoh_product_id` (`PRODUCT_ID`),
  CONSTRAINT `FK_product_qoh_product_id` FOREIGN KEY (`PRODUCT_ID`)
  REFERENCES `product` (`PRODUCT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

2. Objet métier produit

Dans cette implémentation 'productBo', la méthodesave() insérera un enregistrement dans la table 'product' via la classe‘productDao 'et un enregistrement de quantité disponible dans le'productQoh 'table via la classe'productQohBo '.

package com.example.product.bo.impl;

import com.example.product.bo.ProductBo;
import com.example.product.bo.ProductQohBo;
import com.example.product.dao.ProductDao;
import com.example.product.model.Product;
import com.example.product.model.ProductQoh;

public class ProductBoImpl implements ProductBo{

    ProductDao productDao;
    ProductQohBo productQohBo;

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    public void setProductQohBo(ProductQohBo productQohBo) {
        this.productQohBo = productQohBo;
    }

    //this method need to be transactional
    public void save(Product product, int qoh){

        productDao.save(product);
        System.out.println("Product Inserted");

        ProductQoh productQoh = new ProductQoh();
        productQoh.setProductId(product.getProductId());
        productQoh.setQty(qoh);

        productQohBo.save(productQoh);
        System.out.println("ProductQoh Inserted");
    }
}

Fichier de configuration du bean Spring.

   
   
    
    
   

   
   
    
   

Exécuter

    Product product = new Product();
    product.setProductCode("ABC");
    product.setProductDesc("This is product ABC");

    ProductBo productBo = (ProductBo)appContext.getBean("productBo");
    productBo.save(product, 100);

Supposons que lesave() ne possède pas la fonction transactionnelle, si une exception est levée parproductQohBo.save(), vous insérerez un enregistrement dans la table 'product' uniquement, aucun enregistrement ne sera inséré dans le 'productQoh 'table. Il s'agit d'un problème grave qui brise la cohérence des données dans votre base de données.

3. Gestion des transactions

Déclaré un bean «TransactionInterceptor», et un «HibernateTransactionManager» pour la transaction Hibernate, et en passant la propriété nécessaire.



    
    
    
       
        PROPAGATION_REQUIRED
       
    
    

    
      
      
    

Attributs de transaction

Dans l’intercepteur de transactions, vous devez définir quels attributs de transaction «propagation behavior» doivent être utilisés. Cela signifie que si une méthode transactionnelle‘ProductBoImpl.save() est appelée une autre méthodeproductQohBo.save(), comment la transaction doit-elle être propagée? Doit-il continuer à s'exécuter dans le cadre de la transaction existante? ou démarrer une nouvelle transaction pour son propre compte.

Il existe 7 types de propagation pris en charge par Spring:

  • PROPAGATION_REQUIRED - Prend en charge une transaction en cours; créez-en un nouveau s'il n'en existe pas.

  • PROPAGATION_SUPPORTS - Prend en charge une transaction en cours; exécuter de manière non transactionnelle s'il n'en existe pas.

  • PROPAGATION_MANDATORY - Prend en charge une transaction en cours; lancer une exception si aucune transaction en cours n'existe.

  • PROPAGATION_REQUIRES_NEW - Crée une nouvelle transaction, suspendant la transaction en cours s'il en existe une.

  • PROPAGATION_NOT_SUPPORTED - Ne prend pas en charge une transaction en cours; exécutez plutôt toujours de manière non transactionnelle.

  • PROPAGATION_NEVER - Ne prend pas en charge une transaction en cours; lancer une exception si une transaction en cours existe.

  • PROPAGATION_NESTED - Exécute dans une transaction imbriquée si une transaction en cours existe, se comporte comme PROPAGATION_REQUIRED sinon.

Dans la plupart des cas, vous devrez peut-être simplement utiliser la PROPAGATION_REQUIRED.

En outre, vous devez également définir la méthode pour prendre en charge ces attributs de transaction. Le nom de la méthode est pris en charge au format générique, unsave * correspondra à tous les noms de méthode commençant par save (…).

Gestionnaire de transactions

Dans la transaction Hibernate, vous devez utiliserHibernateTransactionManager. Si vous ne traitez qu'avec du JDBC pur, utilisezDataSourceTransactionManager; tandis que JTA, utilisezJtaTransactionManager.

4. Bean Proxy Factory

Créez un nouveau bean de fabrique de proxy pourProductBo et définissez la propriété ‘interceptorNames’.

   
   
    
    
   

   
   
    
   

   
    
    
        
            transactionInterceptor
        
    
  

Exécuter

    Product product = new Product();
    product.setProductCode("ABC");
    product.setProductDesc("This is product ABC");

    ProductBo productBo = (ProductBo)appContext.getBean("productBoProxy");
    productBo.save(product, 100);

Obtenez votre bean proxy 'productBoProxy', et votre méthodesave() prend en charge transactionnelle maintenant, toute exception dans la méthodeproductBo.save() entraînera l'annulation de toute la transaction, aucune donnée ne sera insérée dans la base de données .

Télécharger le code source