English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Dettagli della gestione delle transazioni di Springboot

In the transaction management of Spring Boot, implement the interface PlatformTransactionManager.

public interface PlatformTransactionManager {
  org.springframework.transaction.TransactionStatus getTransaction(org.springframework.transaction.TransactionDefinition transactionDefinition) throws org.springframework.transaction.TransactionException;
  void commit(org.springframework.transaction.TransactionStatus transactionStatus) throws org.springframework.transaction.TransactionException;
  void rollback(org.springframework.transaction.TransactionStatus transactionStatus) throws org.springframework.transaction.TransactionException;
}

When we use the spring-boot-starter-jdbc dependency, the framework will automatically default inject DataSourceTransactionManager. Therefore, we do not need any additional configuration to use the @Transactional annotation for transaction usage.

JDBC transaction manager

In the Service, methods annotated with @Transactional will support transactions. If the annotation is on the class, all methods in the class will support transactions by default.

Multiple transaction managers

First: You can implement the TransactionManagementConfigurer interface, and the return value of the method inside is the default transaction manager.

Second: You can set the value on the specific execution method

If there are multiple PlatformTransactionManager instances in the Spring container and no default value is specified by implementing the TransactionManagementConfigurer interface, when we use the @Transactional annotation on a method, we must specify the value. If not specified, an exception will be thrown.

//@EnableTransactionManagement // Enable annotation-based transaction management, equivalent to <tx:annotation-driven /> in the xml configuration file
@SpringBootApplication
public class ProfiledemoApplication implements TransactionManagementConfigurer {
  @Resource(name="txManager2")
  private PlatformTransactionManager txManager2;
  //Manual creation of transaction manager 1, the datasource framework will automatically inject
  //In the Spring container, the @Bean annotation we manually add will be loaded first, and the framework will not re-instantiate other PlatformTransactionManager implementation classes.
  @Bean(name = "txManager1")
  public PlatformTransactionManager txManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
  }
  // Crea il gestore di transazioni 2
  @Bean(name = "txManager2")
  public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
    return new JpaTransactionManager(factory);
  }
  // Implementa l'interfaccia TransactionManagementConfigurer, il valore di ritorno rappresenta il gestore di transazioni predefinito utilizzato in presenza di più gestori di transazioni
  @Override
  public PlatformTransactionManager annotationDrivenTransactionManager() {
    return txManager2;
  }
  public static void main(String[] args) {
    SpringApplication.run(ProfiledemoApplication.class, args);
  }
}

Implementazione specifica

@Component
public class DevSendMessage implements SendMessage {
  // Specificare esplicitamente value per indicare quale gestore di transazioni utilizzare
  @Transactional(value="txManager1")
  @Override
  public void send() {
    System.out.println(">>>>>>>>Invio Dev()<<<<<<<<");
    send2();
  }
  @Transactional
  public void send2() {
    System.out.println(">>>>>>>>Invio Dev2()<<<<<<<<");
  }
}

Isolazione di livello

public enum Isolation {
  DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
  READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
  READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
  REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
  SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
  private final int value;
  Isolation(int value) { this.value = value; }
  public int value() { return this.value; }
}
  1. DEFAULT: Questo è il valore predefinito, che rappresenta il livello di isolamento predefinito del database di basso livello. Per la maggior parte dei database, di solito questo valore è: READ_COMMITTED.
  2. READ_UNCOMMITTED: Questo livello di isolamento indica che una transazione può leggere i dati modificati dall'altra transazione ma non ancora sottoposti a transazione. Questo livello non può prevenire la lettura sporca e la lettura non ripetibile, quindi questo livello viene utilizzato raramente.
  3. READ_COMMITTED: Questo livello di isolamento indica che una transazione può leggere solo i dati che sono stati sottoposti a transazione dall'altra parte. Questo livello può prevenire la lettura sporca, che è anche il valore raccomandato nella maggior parte dei casi.
  4. REPEATABLE_READ: Questo livello di isolamento indica che una transazione può eseguire più volte la stessa query durante tutto il suo processo e che ogni volta restituisce lo stesso record. Anche se tra le query vengono aggiunti dati nuovi che soddisfano la query, questi nuovi record vengono ignorati. Questo livello può prevenire la lettura sporca e la lettura non ripetibile.
  5. SERIALIZABLE: Tutte le transazioni vengono eseguite in sequenza una dopo l'altra, in modo che tra le transazioni non si possano verificare interferenze, ossia, a questo livello si può prevenire la lettura sporca, la lettura non ripetibile e la lettura fantasma. Tuttavia, ciò influenzerà significativamente le prestazioni del programma. Di solito non si utilizza questo livello.

Specificazione del metodo: utilizzando l'attributo isolation, ad esempio:

@Transactional(isolation = Isolation.DEFAULT)

Comportamento di propagazione

Il comportamento di propagazione della transazione si riferisce al fatto che, se prima dell'inizio della transazione corrente esiste già un contesto di transazione, ci sono diverse opzioni per specificare il comportamento di esecuzione di un metodo transazionale.

Possiamo vedere che la classe enumerativa org.springframework.transaction.annotation.Propagation definisce sei valori enumerativi che rappresentano i comportamenti di propagazione:

public enum Propagation {
  REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
  SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
  MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
  REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
  NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
  NEVER(TransactionDefinition.PROPAGATION_NEVER),
  NESTED(TransactionDefinition.PROPAGATION_NESTED);
  private final int value;
  Propagation(int value) { this.value = value; }
  public int value() { return this.value; }
}

REQUIRED: se esiste una transazione corrente, si unisce a questa transazione; se non esiste alcuna transazione, crea una nuova transazione. Valore predefinito.

SUPPORTS: se esiste una transazione corrente, si unisce a questa transazione; se non esiste alcuna transazione, continua a eseguire in modo non transazionale.

MANDATORY: se esiste una transazione corrente, si unisce a questa transazione; se non esiste alcuna transazione, lancia un'eccezione. (Forzato in una transazione)

REQUIRES_NEW: crea una nuova transazione, se esiste una transazione corrente, sospende la transazione corrente. (Utilizzato spesso per stampare i log, anche se viene fatto il rollback, questa transazione verrà eseguita, registrando le informazioni di errore)

NOT_SUPPORTED: eseguito in modo non transazionale, se esiste una transazione corrente, sospende la transazione corrente.

NEVER: eseguito in modo non transazionale, se esiste una transazione corrente, lancia un'eccezione.

NESTED: se esiste una transazione corrente, crea una transazione come transazione annidata per l'esecuzione della transazione corrente; se non esiste alcuna transazione, questo valore è equivalente a REQUIRED.

Metodo specifico: impostando l'attributo propagation, ad esempio:

@Transactional(propagation = Propagation.REQUIRED)

Casi di non rollback

Il rollback avviene solo quando si verifica un RuntimeException non catturato

catch l'eccezione lanciata, entrambe le inserzioni avranno successo

@Override
  @Transactional
  public void insertandinsert(Staff staff) {
    staffDao.insert(staff);
    try {
      int i = 1 / 0;
    }catch (Exception e){
      e.printStackTrace();
    }
    staffDao.insert(staff);
  }

Aggiungi la frase TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); nella frase catch del metodo del livello di servizio per rollback manuale e non inserire dati.

@Override
  @Transactional
  public void insertandinsert(Staff staff) throws Exception {
    try {
      staffDao.insert(staff);
      int i=1/0;
      staffDao.insert(staff);
    }catch (Exception e){
      TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
  }

Questo è tutto il contenuto dell'articolo, spero che sia utile per la tua apprendimento e che tu sostenga fortemente la guida a urlania.

Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, di proprietà del rispettivo autore. Il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, il sito web non detiene i diritti di proprietà, non è stato sottoposto a editing umano e non assume alcuna responsabilità legale. Se trovi contenuti sospetti di copyright, invia un'e-mail a notice#oldtoolbag.com (sostituisci # con @) per segnalare il problema e fornire prove pertinenti. Una volta verificata, il sito web rimuoverà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare