1. Princípios básicos de transações
A essência das transações de primavera é na verdade o suporte do banco de dados para transações. Sem suporte à transação do banco de dados, o Spring não pode fornecer funções de transação. Para bancos de dados operacionais puro do JDBC, se você quiser usar transações, poderá seguir as seguintes etapas:
1. Obtenha a conexão Connection Con = DriverManager.getConnection ()
2. Abra a transação Con.SetAutocomit (true/false);
3. Execute Crud
4. Transação de comprometimento / transação de reversão Con.Commit () / Con.Rollback ();
5. Feche a conexão Conn.Close ();
Depois de usar a função de gerenciamento de transações da Spring, não podemos mais escrever o código nas etapas 2 e 4, mas será feito automaticamente pela Spirng. Então, como a primavera aberta e fecha transações antes e depois do crud que escrevemos? Ao resolver esse problema, podemos entender o princípio da implementação do gerenciamento de transações da Spring de um todo. Deixe -me apresentar brevemente o método de anotação como exemplo
1. Ligue o driver de anotação no arquivo de configuração e identifique -o anotando o @Transaction nas classes e métodos relevantes.
2. Quando a primavera começar, analisará e gerará feijão relacionado. No momento, ele verificará as classes e métodos com anotações relevantes e gerará um proxy para essas classes e métodos e realizará a injeção de configuração relacionada com base nos parâmetros relevantes do @Transaction, para que as transações relevantes sejam processadas para nós no proxy (transações normais de inicialização e transações de exceção).
3. Comprometimento de transação e reversão da camada real do banco de dados são implementadas através do binlog ou do log de refazer.
2. Propriedades de propagação das transações de primavera
O chamado atributo de propagação das transações de mola define como a mola deve lidar com o comportamento de várias transações quando elas existem ao mesmo tempo. Essas propriedades são definidas na transação. As constantes específicas são explicadas na tabela a seguir:
Iii. Nível de isolamento do banco de dados
Leitura suja: uma transação adiciona, exclui e modifica os dados, mas não está comprometida, e outra transação pode ler dados não comprometidos. Se a primeira transação voltar neste momento, a segunda transação lê dados sujos.
Sem leitura repetitiva: duas operações de leitura ocorrem em uma transação. Entre a primeira operação de leitura e a segunda operação, a outra transação modifica os dados. Neste momento, os dados lidos duas vezes são inconsistentes.
Leitura de fantasia: a primeira transação modifica os dados em um determinado intervalo em lotes, e a segunda transação adiciona um dados a esse intervalo. No momento, a primeira transação perderá a modificação dos dados recém -adicionados.
Resumir :
Quanto maior o nível de isolamento, mais ele pode garantir a integridade e a consistência dos dados, mas maior o impacto no desempenho da simultaneidade.
O nível de isolamento padrão da maioria dos bancos de dados é lido comissionado, como SQLServer e Oracle
O nível de isolamento padrão de alguns bancos de dados é: Leia repetível, por exemplo: mysql innodb
4. Nível de isolamento na primavera
V. Ninho de transações
Através do conhecimento teórico acima, entendemos aproximadamente alguns atributos e características das transações de banco de dados e transações de mola. Em seguida, analisamos alguns cenários de transação aninhados para entender profundamente o mecanismo da propagação da transação da mola.
Suponha que o método a () do serviço de transação externa a chama o método b () do serviço interno B
Propagation_required (padrão de primavera)
Se o nível de transação do serviçob.methodb () for definido como propagation_required, então quando o Servicea.methoda () for executado, a transação já foi iniciada na primavera. Neste momento, o serviçob.methodb () é chamado. ServiceB.MethodB () vê que está sendo executado dentro da transação do Servicea.methoda () e nenhuma nova transação é iniciada.
Se o serviçob.methodb () estiver em execução, ele atribuirá uma transação a si mesma.
Dessa forma, se ocorrer uma exceção em Servicea.methoda () ou em qualquer lugar do serviçob.methodb (), a transação será revertida.
Propagation_requires_new
Por exemplo, projetamos que o Servicea.methoda () possui um nível de transação de propagação_required, e o serviçob.methodb () possui um nível de transação de propagation_requires_new.
Então, quando o serviçob.methodb () for executado, a transação em que o servicea.methoda () estiver localizada será suspensa e o serviçob.methodb () iniciará uma nova transação e continuará sendo executado após a conclusão da transação do serviçob.methodb ().
A diferença entre suas transações e propagação_required é o grau de reversão da transação. Como o serviçob.methodb () é uma nova transação, existem duas transações diferentes. Se o serviçob.methodb () tiver sido enviado, o Servicea.methoda () falhar em reversão, o serviçob.methodb () não será revertido. Se o serviçob.methodb () não reverter, se a exceção lançada pelo servicea.methoda () for capturada, a transação Servicea.methoda () ainda poderá ser enviada (principalmente depende se a exceção lançada por B é uma exceção de que uma reversão).
Propagation_supports
Supondo que o nível de transação do serviçob.methodb () seja propagation_supports, quando é executado em serviçob.methodb (), se for encontrado que o Servicea.methoda () abriu uma transação, ele ingressará a transação atual. Se for constatado que o Servicea.methoda () não iniciou a transação, ele não iniciará a própria transação. Neste momento, a transacionalidade do método interno depende inteiramente da transação mais externa.
Propagation_nested
A situação está se tornando mais complicada agora. A propriedade de transação do serviçob.methodb () é configurada como propagation_nested. Como os dois cooperarão neste momento? ServiceB#MethodB Se reversão, as transações internas (ou seja, ServiceB#MethodB) voltarão ao SalvarPoint antes de executar, enquanto transações externas (ou seja, Servicea#Methoda) podem ter as seguintes duas maneiras de manusear:
um. Catch exceções e executar a lógica da filial de exceção
void MethodA () {Try {ServiceB.Methodb (); } catch (somexception) {// Execute outros negócios, como servicec.methodc (); }} Este método também é a coisa mais valiosa sobre transações aninhadas. Ele desempenha o papel da execução da filial. Se o serviçob.methodb falhar, o servicec.methodc () será executado e o serviçob.methodb voltou ao salvamento antes que ele seja executado, para que nenhum dados sujo seja gerado (equivalente a esse método nunca sendo executado). Esse recurso pode ser usado em alguns serviços especiais, e nem o propagation_required nem propagation_requires_new podem fazer isso.
b. O código de reversão/comprometimento da transação externa não faz nenhuma modificação. Se a transação interna (ServiceB#MethodB) Rollback, primeiro o serviçob.methodb voltar ao SalvePoint antes que ele seja executado (em qualquer caso) e a transação externa (ou seja, o Servicea#Methoda) decidirá se ele confirmar ou reverter com base na configuração específica.
Os outros três atributos de propagação da transação são basicamente ineficazes, portanto, nenhuma análise é feita aqui.
6. Resumo
Para lugares onde são necessárias transações no projeto, sugiro que os desenvolvedores usem a interface TransactionCallback da Spring para implementar transações. Não use cegamente as anotações da transação de primavera. Se você precisar usar anotações, deve ter um entendimento detalhado do mecanismo de propagação e do nível de isolamento das transações de mola, caso contrário, poderão ocorrer efeitos inesperados.