Spring AOP-Transaktionsverwaltung in Hibernate

Transaktionsmanagement ist erforderlich, um die Datenintegrität und -konsistenz in der Datenbank sicherzustellen. Die AOP-Technik von Spring ermöglicht Entwicklern die Verwaltung der Transaktionsdeklaration.

Hier ein Beispiel, das zeigt, wie die Hibernate-Transaktion mit Spring AOP verwaltet wird.

__P.S Viele Hibernate- und Spring-Konfigurationsdateien sind ausgeblendet, es werden nur einige wichtige Dateien angezeigt. Wenn Sie Hand-On wünschen, laden Sie das vollständige Projekt am Ende des Artikels herunter.

1. Tabellenerstellung

MySQL-Tabellenskripte, eine Produkttabelle und eine Produktmenge .

CREATE TABLE  `mkyong`.`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  `mkyong`.`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. Geschäftsobjekt des Produkts

In dieser ' productBo '-Implementierung fügt die save () -Methode einen Datensatz in die' product '-Tabelle über die Klasse ' productDao ' ein, und einen Mengenbestand in die ' productQoh ' - Tabelle über Klasse " productQohBo ".

package com.mkyong.product.bo.impl;

import com.mkyong.product.bo.ProductBo;
import com.mkyong.product.bo.ProductQohBo;
import com.mkyong.product.dao.ProductDao;
import com.mkyong.product.model.Product;
import com.mkyong.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");
    }
}

Die Bean-Konfigurationsdatei von Spring.

   <!-- Product business object -->
   <bean id="productBo" class="com.mkyong.product.bo.impl.ProductBoImpl" >
    <property name="productDao" ref="productDao"/>
    <property name="productQohBo" ref="productQohBo"/>
   </bean>

   <!-- Product Data Access Object -->
   <bean id="productDao" class="com.mkyong.product.dao.impl.ProductDaoImpl" >
    <property name="sessionFactory" ref="sessionFactory"></property>
   </bean>

Starte es

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

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

Angenommen, save () verfügt nicht über die Transaktionsfunktion. Wenn eine Ausnahme durch productQohBo.save () ausgelöst wird, werden Sie nur einen Datensatz in die ' product ' - Tabelle einfügen. productQoh ** 'Tabelle. Dies ist ein ernstes Problem und unterbricht die Datenkonsistenz in Ihrer Datenbank.

3. Transaktionsmanagement

Deklarierte eine "** TransactionInterceptor" -Bean und einen "HibernateTransactionManager" für die Hibernate-Transaktion und übergab die erforderliche Eigenschaft.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="transactionInterceptor"
       class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
       <props>
        <prop key="save">PROPAGATION__REQUIRED</prop>
       </props>
    </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
      <property name="dataSource" ref="dataSource"/>
      <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

</beans>
Transaktionsattribute

In Transaction Interceptor müssen Sie festlegen, welche Attribute der Transaktion "Ausbreitungsverhalten" verwendet werden sollen. Dies bedeutet, wenn eine transaktionale "ProductBoImpl.save () " -Methode eine andere Methode " productQohBo.save () " heißt, wie soll die Transaktion propagiert werden?

Sollte es innerhalb der bestehenden Transaktion weiterlaufen? oder starten Sie eine neue Transaktion für sich.

Spring unterstützt sieben Ausbreitungsarten:

Eins, wenn keiner existiert.

  • PROPAGATION__SUPPORTS - Unterstützung einer aktuellen Transaktion; ausführen

nicht transaktionsfähig, wenn keine vorhanden ist.

  • PROPAGATION__MANDATORY - Unterstützung einer aktuellen Transaktion; werfen ein

Ausnahme, wenn keine aktuelle Transaktion vorhanden ist.

  • PROPAGATION REQUIRES NEW - Erstellen Sie eine neue Transaktion und setzen Sie die

Aktuelle Transaktion, falls vorhanden.

  • PROPAGATION NOT SUPPORTED - Keine aktuelle Transaktion unterstützen;

vielmehr immer untransaktional ausführen.

  • PROPAGATION__NEVER - Keine aktuelle Transaktion unterstützen; werfen ein

Ausnahme, wenn eine aktuelle Transaktion vorhanden ist.

  • PROPAGATION__NESTED - Wird innerhalb einer geschachtelten Transaktion ausgeführt, wenn a

Aktuelle Transaktion ist vorhanden, verhalten Sie sich wie PROPAGATION__REQUIRED

In den meisten Fällen müssen Sie möglicherweise nur PROPAGATION__REQUIRED verwenden.

Darüber hinaus müssen Sie die Methode definieren, die auch diese Transaktionsattribute unterstützt. Der Methodenname wird im Wildcard-Format unterstützt. Ein save ** entspricht allen Methodennamen, die mit save (…​) beginnen.

Transaction Manager

In der Hibernate-Transaktion müssen Sie HibernateTransactionManager verwenden.

Wenn Sie nur mit reiner JDBC arbeiten, verwenden Sie DataSourceTransactionManager ; Verwenden Sie während der JTA JtaTransactionManager .

4. Proxy Factory Bean

Erstellen Sie eine neue Proxy-Factory-Bean für ProductBo und legen Sie die Eigenschaft interceptorNames

   <!-- Product business object -->
   <bean id="productBo" class="com.mkyong.product.bo.impl.ProductBoImpl" >
    <property name="productDao" ref="productDao"/>
    <property name="productQohBo" ref="productQohBo"/>
   </bean>

   <!-- Product Data Access Object -->
   <bean id="productDao" class="com.mkyong.product.dao.impl.ProductDaoImpl" >
    <property name="sessionFactory" ref="sessionFactory"></property>
   </bean>

   <bean id="productBoProxy"
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="productBo"/>
    <property name="interceptorNames">
        <list>
            <value>transactionInterceptor</value>
        </list>
    </property>
  </bean>

Starte es

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

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

Holen Sie sich Ihre Proxy-Bean ' productBoProxy ' und Ihre save () -Methode unterstützt jetzt Transaktionsfunktionen. Alle Ausnahmen in der productBo.save () -Methode führen dazu, dass die gesamte Transaktion rückgängig gemacht wird. In die Datenbank werden keine Daten eingefügt .

Quellcode herunterladen