A principal pesquisa deste artigo é a propagação da transação de primavera e seus princípios de implementação, que são introduzidos da seguinte forma.
Atualmente, a Spring é um padrão de fato para o desenvolvimento de Java, graças à sua conveniência, funções completas e fácil de usar. Durante o processo de desenvolvimento, o Operating DB é uma operação muito comum e, quando se trata de DB, envolve transações. Durante o processo de desenvolvimento normal de transações, mesmo que você não o notar, não haverá efeitos colaterais na execução normal do programa. No entanto, se ocorrer uma exceção e a transação não for tratada adequadamente, pode ocorrer resultados inesperados. A Spring encapsulou várias operações em termos de transações, especialmente o surgimento de transações declarativas, tornando o desenvolvimento mais confortável. A primavera expande as transações e suporta a definição de múltiplos atributos de propagação, que também é o foco deste artigo.
Não falando estritamente, uma transação é a abreviação de várias operações. Essas operações entram em vigor ou nenhuma delas entra em vigor (equivalente a não ser executada). Um processo de operação geral é simplificado da seguinte maneira:
tente {conexão conn = getConnection (); // Execute algumas operações de banco de dados} Catch (Exceção e) {Conn.Rollback ();} finalmente {Conn.Close ();}Alguns problemas podem ser vistos no código acima:
A primavera fornece transações declarativas, portanto, não precisamos prestar atenção à implementação específica da camada subjacente e bloqueia muitos detalhes diferentes de implementação da camada subjacente. Para apoiar o controle fino das transações por vários negócios complexos, a Spring fornece os atributos de propagação das transações e combinada com transações declarativas, tornou -se uma ferramenta de transação importante.
Na classe TransactionDefinition, a Spring fornece 6 propriedades de propagação, que são explicadas com exemplos simples.
Lembrete quente: o seguinte mencionado unindo a transação atual refere -se ao uso da mesma conexão na parte inferior, mas o objeto do estado da transação pode ser recriado e não o afeta. O artigo mencionou que há apenas uma transação no momento, o que significa que a conexão subjacente é compartilhada e não se importa com quantos objetos de estado da transação (transactionStatus) são criados.
Descrição: Se já existir uma transação, participe da transação. Se não houver transação, crie uma transação. Este é o valor do atributo de propagação padrão.
Vamos ver um pequeno exemplo, o código é o seguinte:
@Transactionalpublic void Service () {servicea (); ServiceB ();}@transactionalServicea ();@transactionalServiceB ();Servicea e ServiceB declaram transações. Por padrão, propagação = propagation_required. Durante todo o processo de chamada de serviço, há apenas uma transação compartilhada. Quando ocorrer qualquer exceção, todas as operações serão revertidas.
Descrição: Se já existir uma transação, participe da transação, caso contrário, a chamada transação vazia será criada (ela pode ser considerada como não execução de transações).
Vamos ver um pequeno exemplo, o código é o seguinte:
public void Service () {servicea (); lançar novo RUNTimeException ();}@transactional (propagação = propagação.supports) servicea ();Atualmente, não há transação quando o Servicea estiver executando, portanto, a exceção lançada no serviço não fará com que o Servicea seja revertido.
Vamos dar uma olhada em outro pequeno exemplo, o código é o seguinte:
public void Service () {servicea ();}@transactional (propagação = propagação.supports) servicea () {do sql 1 1/0; do SQL 2}Como o Servicea não tem transações ao ser executado, neste momento, se a fonte de dados subjacente DefaultAutocommit = true, o SQL1 for eficaz. Se defaultAutocommit = false, então o SQL1 é inválido. Se o serviço tiver a tag @Transactional, o Servicea compartilha as transações de serviço (não depende mais do DefaultAutocommit). Neste momento, o Servicea está revertido.
Descrição: Atualmente, uma transação deve existir, caso contrário, uma exceção será lançada.
Vamos ver um pequeno exemplo, o código é o seguinte:
public void Service () {ServiceB (); servicea ();} serviceB () {do sql} @transaction (propagação = propagação.mandatory) servicea () {do sql}Nesse caso, a execução do serviço lançará uma exceção. Se DefaultAutocommit = true, o ServiceB não voltará. Se DefaultAutocommit = False, a execução do ServiceB será inválida.
Nota: Se atualmente existir uma transação, primeiro encapsulará o conteúdo atual relacionado à transação em uma entidade, depois recrie uma nova transação, aceite essa entidade como um parâmetro e use-a para recuperação de transações. Uma declaração mais contundente é suspender a transação atual (nenhuma transação é necessária) e criar uma nova transação. Nesse caso, não há dependência entre as duas transações, e a nova transação pode ser revertida, mas a transação externa continua a executar.
Vamos ver um pequeno exemplo, o código é o seguinte:
@TransactionalPublic void Service () {ServiceB (); tente {servicea (); } catch (Exceção e) {}} serviceB () {do sql} @transaction (propagação = propagação.requis_new) servicea () {do sql 1 1/0; do SQL 2}Ao chamar a interface de serviço, como o Servicea usa requer_new, ele criará uma nova transação. No entanto, como o Servicea lança uma exceção de tempo de execução, o Servicea é revertido. No método de serviço, as exceções são capturadas, portanto o serviçob é enviado normalmente. Observe que a tentativa ... o código de captura no serviço é necessário; caso contrário, o serviço lançará uma exceção, fazendo com que o ServiceB seja revertido.
Nota: Se atualmente existir uma transação, suspenda a transação atual e, em seguida, o novo método será executado em um ambiente sem transações e em um ambiente sem transações de primavera, a confirmação do SQL depende completamente do valor da propriedade DefaultAutocomit.
Vamos ver um pequeno exemplo, o código é o seguinte:
@TransactionalPublic void Service () {ServiceB (); servicea ();} serviceB () {do sql} @transaction (propagation = propagation.not_supported) servicea () {do sql 1 1/0; do SQL 2}Quando o método de serviço é chamado, uma exceção é lançada quando o código 1/0 no método Servicea é executado. Como o Servicea está em um ambiente livre de transações, se o SQL1 é eficaz depende do valor do DefaultAutocomit. Quando DefaultAutocommit = true, o SQL1 é eficaz, mas o ServiceB será revertido porque o serviço lança uma exceção.
Descrição: Se uma transação estiver presente atualmente, uma exceção será lançada, caso contrário, o código será executado em um ambiente sem transação.
Vamos ver um pequeno exemplo, o código é o seguinte:
public void Service () {ServiceB (); servicea ();} serviceB () {do sql} @transaction (propagation = propagation.never) servicea () {do sql 1 1/0; do SQL 2}Após o exemplo acima, chama o serviço, se DefaultAutocommit = true, o método ServiceB e o SQL1 no Servicea entrarão em vigor.
NOTA: Se atualmente existir uma transação, use a tecnologia SavePoint para salvar o estado de transação atual e, em seguida, a camada subjacente compartilha uma conexão. Quando um erro ocorre dentro do aninhado, ele voltará ao estado do SavePoint por si só. Enquanto uma exceção for capturada por fora, ele pode continuar a cometer transações externas sem ser perturbado pelos negócios incorporados. No entanto, se uma exceção for lançada pela transação externa, toda a grande transação será revertida.
NOTA: O gerenciador de transações de configuração da mola deve especificar ativamente o NesterTransactionAllowed = true, como mostrado abaixo:
<bean id = "DataTransactionManager"> <propriedade name = "DataSource" ref = "datadataSource" /> <nome da propriedade = "NtestransactionAllowed" value = "true" /> </shean>
Veja um pequeno exemplo, o código é o seguinte:
@Transactionalpublic void Service () {servicea (); tente {serviceB (); } catch (Exceção e) {}} servicea () {do sql} @transaction (propagação = propagação.nested) serviceB () {do sql1 1/0; do sql2}O ServiceB é um serviço incorporado e uma exceção de tempo de execução é lançada internamente, então o ServiceB é revertido. Como o serviço pegou a exceção, o Servicea pode enviá -lo normalmente.
Vamos dar uma olhada em outro exemplo, o código é o seguinte:
@Transactionalpublic void Service () {servicea (); ServiceB (); 1/0;}@transacional (propagação = propagação.nested) servicea () {do sql} serviceB () {do sql}Como o serviço lança uma exceção, todo o método de serviço será revertido. (Isso é diferente de propagation_requires_new. Os serviços incorporados no modo aninhado serão revertidos por exceções de transações externas.)
Os exemplos acima ilustram vários atributos de propagação fornecidos pelas transações de primavera são usados para atender a uma variedade de necessidades comerciais diferentes, que podem ser determinadas pelos negócios. Em seguida, vamos dar uma olhada no que as dependências técnicas mais importantes do Spring implementam esses atributos de propagação. Esta seção lista propagation_requires_new e propagação.nested para breves descrições, respectivamente.
A seguinte chamada de código:
@TransactionalPublic void Service () {ServiceB (); tente {servicea (); } catch (Exceção e) {}}@transactional (propagação = propagação.requis_new) servicea () {do sql 1 1/0; do sql 2} serviceB () {do sql}O esquema de execução é o seguinte:
um. Crie um objeto de estado de transação, obtenha uma nova conexão, redefinir a autocomércia, buscar o tempo limite e outras propriedades da conexão
b. Vincular a conexão com a variável Threadlocal
c. Pendente da transação atual, encapsulando o objeto de estado de transação atual, conexão e outras informações em um objeto SuspendedResources, que pode ser usado para recuperação
d. Crie um novo objeto de estado de transação, reacique uma nova conexão, redefina a autocomércia, busque, tempo limite e outras propriedades da nova conexão. Ao mesmo tempo, salve o objeto SuspendedResources para recuperação da transação e vincule a nova conexão à variável Threadlocal (operação de substituição)
e. Pegue uma exceção, recua a conexão no Threadlocal, restaure os parâmetros de conexão, feche a conexão e restaure SuspendedResources
f. Envie a conexão na variável Threadlocal (fazendo o serviço do ServiceB ser enviado), restaure os parâmetros de conexão, feche a conexão e retorne a conexão com a fonte de dados
Portanto, o resultado da execução do programa é que o Servicea é revertido e o ServiceB é enviado com sucesso.
A seguinte chamada de código:
@Transactionalpublic void Service () {servicea (); tente {serviceB (); } catch (Exceção e) {}} servicea () {do sql} @transaction (propagação = propagação.nested) serviceB () {do sql1 1/0; do sql2}O esquema de execução é o seguinte:
um. Crie um objeto de estado de transação, obtenha uma nova conexão, redefinir a autocomércia, buscar o tempo limite e outras propriedades da conexão
b. Vincular a conexão com a variável Threadlocal
c. Marque o uso do objeto atual do estado da transação, obtenha o objeto de conexão Threadlocal, salve o SalvePoint da conexão atual e é usado para recuperação de exceção. Neste momento, o SalvePoint é o status após a execução da servicea
d. Pegue uma exceção e use o SavePoint em C para reversão de transações, ou seja, reverter o estado para o estado depois de executar o Servicea. Todas as execuções dos métodos do ServiceB não entram em vigor
e. Obtenha o objeto de conexão no ThreadLocal, envie transações, restaurar propriedades de conexão, conexão próxima
Com base na fonte de dados subjacente, o Spring usa Threadlocal, SavePoint e outros pontos técnicos para realizar uma variedade de atributos de propagação de transações, o que facilita a implementação de vários serviços complexos. Somente entendendo o princípio dos atributos de propagação, podemos controlar melhor as transações de mola. As transações de reversão primavera dependem da captura de exceções. Por padrão, as transações só serão revertidas se a tempo de execução e o erro forem lançados. Claro, pode ser configurado. Para mais informações, você pode verificar a anotação @Transaction.
As transações declarativas da primavera nos trazem grande conveniência. Para fazer bom uso dessa arma, ainda é necessário entender os princípios subjacentes. Este artigo é apenas a ponta do iceberg das transações de primavera. Os leitores podem explorar em profundidade nessa base.
O exposto acima é todo o conteúdo deste artigo sobre a propagação da transação de primavera e seus princípios de implementação. Espero que seja útil para todos. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!