Este artigo realizará pesquisas aprofundadas sobre o gerenciamento de transações da primavera. Apresenta principalmente como o @transaction funciona na parte inferior. O artigo a seguir será introduzido:
Uso de atributos como propagação (propagação da transação) e isolamento (isolamento)
Quais são as armadilhas do uso da transação e como evitá -lo
JPA e gerenciamento de transações
É importante que a própria JPA não forneça nenhum tipo de gerenciamento de transações declarativas. Se você usar o JPA fora de um recipiente de injeção de dependência, a transação deve ser implementada programaticamente pelo desenvolvedor.
UserTransaction utx = entityManager.gettransaction (); try {utx.begin (); BusinessLogic (); utx.Commit ();} Catch (Exception Ex) {utx.rollback (); tlowex;}Essa maneira de gerenciamento de transações permite que o escopo da transação seja claramente expresso no código, mas tem as seguintes desvantagens:
Código repetido e erros são propensos a
Quaisquer erros podem ter um impacto maior
Erros são difíceis de depurar e reproduzir
Reduz a legibilidade da base de código
E se o método chamar outros métodos de transação?
Usando a primavera @transaction
Usando o Spring @Transaction, o código acima é simplificado para:
@Transaction PublicVoid BusinessLogic () {... Use Entity Manager dentro de uma transação ...}O código é mais conciso e legível, e também é a maneira recomendada de lidar na primavera atualmente.
Muitos aspectos importantes, como a propagação da transação, podem ser tratados automaticamente usando @Transactional. Nesse caso, se o BusinessLogic () chamar outro método de transação, o método determinará como ingressar na transação em execução com base nas opções.
Uma desvantagem potencial desse mecanismo poderoso é que ele esconde a operação subjacente e é difícil de depurar quando não funciona corretamente.
@Transaction Significado
Um dos pontos -chave sobre @Transaction é considerar dois conceitos separados, os quais têm seu próprio escopo e ciclo de vida:
contexto de persistência (contexto de persistência)
Transação de banco de dados
@Transaction Define o escopo de uma única transação. Essa transação está dentro do escopo do contexto de persistência.
O contexto de persistência no JPA é o EntityManager, e a implementação interna usa a sessão de hibernato (usando o Hibernate como provedor de persistência).
O contexto de persistência é apenas um objeto síncrono que registra o estado dos objetos Java de uma coleção finita e garante que as alterações nesses objetos sejam finalmente persistidos no banco de dados.
Este é um conceito muito diferente de uma única transação. Um gerente de entidade pode ser usado em várias transações e é realmente usado dessa maneira.
Quando o EntityManager abre várias transações?
A situação mais comum é quando um aplicativo usa sessão aberta no modo de exibição para lidar com exceções de inicialização preguiçosa. Artigos anteriores introduziram as vantagens e desvantagens dessa abordagem.
Nesse caso, várias consultas executadas pela camada de visualização estão em transações separadas, em vez de lógica de negócios de transações únicas, mas essas consultas são gerenciadas pelo mesmo gerente de entidade.
Outro cenário é que o desenvolvedor marca o contexto de persistência como persistencecontextType.extended, o que significa que é capaz de responder a várias solicitações.
Como definir o relacionamento entre entityManager e transação?
Isso é escolhido pelos desenvolvedores de aplicativos, mas a maneira mais comum para o JPA Entity Manager é o modo "Entity Manager por transação de aplicativo". Os métodos comuns de injeção do gerente de entidades são:
@PersistencEContext privateentityManager em;
O padrão é o modo "Entity Manager por transação". Nesse modo, se o gerenciador de entidades for usado dentro do método @Transaction, o método será executado em uma única transação.
Como funciona o @persistencecontext?
A pergunta que se segue é como o @PersistenceContext pode injetar o gerenciador de entidades apenas quando o contêiner é iniciado, assumindo que o ciclo de vida do Entity Manager seja curto e requer vários gerentes de entidade por solicitação.
A resposta é que não pode: o entityManager é uma interface e o que é injetado no feijão da primavera não é o próprio gerente de entidade, mas o proxy do contexto (proxy ciente do contexto) do gerenciador de entidades específico no tempo de execução.
A classe específica comumente usada para proxy é compartilhada em managerinvocationhandler, que pode ser confirmada com a ajuda de um depurador.
Então, como funciona o @transactional?
O proxy persistente de contexto que implementa a interface EntityManager não é a única parte do gerenciamento de transações declarativas, mas na verdade contém três componentes:
EntityManager Proxy em si
A seção da transação
Gerente de transações
Dê uma olhada nessas três partes e suas interações.
A seção da transação
A seção de transações é uma seção "em torno" que pode ser chamada antes e depois do método de negócios anotado. A classe específica que implementa a seção é o transactionInterceptor.
Existem duas responsabilidades principais na seção de uma transação:
Em 'antes', a seção fornece um ponto de chamada para decidir se o método de negócios chamado deve ser executado dentro do escopo da transação em andamento ou iniciar uma nova transação independente.
Em 'depois', a seção precisa determinar que a transação é comprometida, revertida ou continuada a funcionar.
Em 'antes', a seção de transações em si não contém nenhuma lógica de decisão, e a decisão de iniciar uma nova transação é delegada ao gerente de transações para conclusão.
Gerente de transações
O gerente de transações precisa resolver os dois problemas a seguir:
O novo gerente de entidades deve ser criado?
Uma nova transação deve ser iniciada?
Isso exige que as seções de transação sejam determinadas quando a lógica 'antes' é chamada. As decisões do gerente de transações são baseadas nos dois pontos a seguir:
A transação está acontecendo
A propriedade de propagação do método de transação (por exemplo, requer_new sempre inicia uma nova transação)
Se o gerenciador de transações determinar que você deseja criar uma nova transação, ele:
1. Crie um novo gerente de entidade
2. O gerente de intilidade está vinculado ao tópico atual
3. Obtenha a conexão do pool de conexão do banco de dados
4. Ligue a conexão com o fio atual
Use a variável Threadlocal para vincular o gerenciador de entidades e a conexão do banco de dados ao thread atual.
As transações são executadas quando são armazenadas no encadeamento e, quando não estão mais em uso, o gerente de transação decide se deve limpá -los.
Qualquer parte do programa pode ser recuperada do thread se o gerenciador de entidades atual e a conexão do banco de dados forem necessários.
EntityManager Proxy
A EntityManager Proxy (já introduzida anteriormente) é a última parte do quebra -cabeça. Quando o método de negócios chama EntityManager.Persist (), isso não é chamado diretamente pelo gerente de entidade.
Em vez disso, o método de negócios chama o agente, que recebe o atual gerente de entidade do thread. Como mencionado anteriormente, o gerenciador de transações vincula o gerente de entidade ao thread.
Depois de entender as várias partes do mecanismo @Transactional, vamos dar uma olhada nas configurações de mola comumente usadas que o implementam.
Integrar três partes
Como combinar três partes para que as anotações da transação possam funcionar corretamente? Primeiro defina a fábrica do Entity Manager.
Isso permite que você injete proxy do gerente de entidades com anotação de contexto de persistência.
@Configuration publicClass entityManagerFactoryConfiguration {@AUTOWIRED PRIVATASTATASource DataSource; @Bean (name = "entityManagerFactory") publicLocalContainerEntityManagerFactoryBean emf () {LocalContaiRentityManagerFactoryBean Emf = ... emf.SetD.SetD.SetDAs () {LocalcontaiRentityManagerFactoryBean Emf = ... emf.SetD.SetD.SetD.SeSTAs. newstring [] {"your.package"}); emf.setjpavendorAdapter (newhibernateJPavendorAdapter ()); returnEmf;}}A próxima etapa é configurar o gerenciador de transações e aplicar as facetas de transação na classe anotada @Transaction.
@Configuration @enabletransactionManagement PublicClass transactionManagersConfig {@AUTOWIRED ENTITYMANAGERFACTORY EMF; @AUTOWIRED PRIVATATATATASource DataSource; @Bean (Name = "TransactionManager") PublicPlatformtransactionManager newjpatransactionManager (); tm.SetentityManagerFactory (EMF); tm.SetDataSource (DataSource); Returnm;}}Anotação @enabletransactionManagement notifica a primavera que a classe anotada por @Transaction é cercada pelo corte da transação. Desta forma, @Transaction pode ser usado.
Resumir
O mecanismo de gerenciamento de transações declarativas da Spring é muito poderoso, mas pode ser mal utilizado ou facilmente configurado erros.
Quando problemas como esse mecanismo não funcionam corretamente ou deixam de alcançar os resultados operacionais esperados, é útil entender seu funcionamento interno.
A coisa mais importante a lembrar é levar em consideração dois conceitos: transações e contextos de persistência, cada um com seu próprio ciclo de vida óbvio que é ilegível.
O exposto acima é todo o conteúdo deste artigo sobre o princípio de trabalho do Spring @Transaction. 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!