Prefácio
Este artigo registra principalmente como a Spring suporta as coisas e como ele pode simplesmente implementar as funções das coisas do banco de dados quando a primavera combina Mybatis. Não vou dizer muito abaixo, vamos dar uma olhada na introdução detalhada juntos.
case1: coisas de apoio à situação em duas tabelas
Primeiro prepare duas mesas, uma tabela de usuários e uma tabela de histórias, a estrutura é a seguinte
Crie a tabela `user` (` id` int (11) não assinada não nula auto_increment, `name` varchar (20) não nulo padrão '' comentário 'nome de usuário',` pwd 'varchar (26) não null default' 'comentário' 'senha', `` isdeled` tinyint (1) não null default '0' ' `atualizada` varchar (13) não padrão nulo '0', chave primária (` id`), key 'name` (`name`)) mecanismo = innodb padrão padrão = utf8mb4; criate tabela'` `` `id` int (11) não assinado não -nulo auto_incrent, '' userid` int (20) Varchar (20) não nulo padrão '' Comentário 'Autor', `Title` Varchar (26) não nulo padrão '' Comentário 'Senha',` `Story` Text Comment Comment 'Content',` `ISDELED` TinyInt (1) não é nulo` `` Varchar ', `Varchar (13) e não nulo' 0 '0',` `atualizou '' 0 ',` criado' e 13) não, não é nulo '0' 0 '0', `` `` `` `` `'' `userID` (` userID`)) mecanismo = innodb padrão padrão = utf8mb4;
Nossa situação é que, quando o usuário modifica o nome, os nomes de ambas as tabelas precisam ser modificados juntos e as inconsistências não são permitidas.
Case2: Suporte de coisa de tabela única
Transferir dinheiro, um usuário reduz o dinheiro, outro usuário aumenta o dinheiro
Crie a tabela `dinheiro` (` id` int (11) não assinada, não nulo auto_incrent, `name` varchar (20) não nulo padrão '' comentário 'nome de usuário',` dinheiro` int (26) não null default '0 comentário' dinheiro '`` isdeled` tinyint (1) e não null default' 0, varchar (13) não nulo padrão '0', chave primária (`id`), chave` name` (`name`)) mecanismo = innodb padrão padrão = utf8mb4;
Comparado ao caso acima, isso é mais simples. Os exemplos a seguir são explicados principalmente com base nisso. Quanto ao caso1, é deixado expandido.
Primeiro, implemente o DAO e a entidade correspondentes
@Datapublic Class MoneyEntity implementa serializável {private estático final serialversionuid = -7074788842783160025L; private int id; nome de string privado; dinheiro privado int; private int isDeleted; privado int criado; private Int atualizado;} interface pública MoneyDao {MoneyEntity QueryMoney (@param ("id") int userID); // Adicione dinheiro, quando negativo, significa reduzir o dinheiro int incrementMoney (@param ("id") int userID, @param ("addmoney") int addmoney);}O arquivo de mapeador correspondente é
<? xml versão = "1.0" coding = "utf-8"?> <! namespace = "com.git.hui.demo.mybatis.mapper.moneydao"> <sql id = "moneyEntity"> id, `name`,` dinheiro`, `isdeleted`,` criado`, `atualizada ' resultType = "com.git.hui.demo.mybatis.entity.moneyEntity"> selecione <incluir refid = "moneyEntity"/> do dinheiro onde id =#{id} </select> <update id = "incrementMoney"> atualizar dinheiro definido = dinheiro +#{{addMoney> where##{{idan {idsA configuração correspondente da fonte de dados de conexão mybatis
<Bean> <propriedade name = "Localizações"> <Value> ClassPath*: jdbc.properties </value> </propriedade> </bean> <bean id = "datAsource" init-method = "init" Destro-Method = "Close"> <Nome da propriedade = "Driver" Ur/"$ {driver}"/> name = "nome de usuário" value = "$ {nome de usuário}"/> <propriedade name = "senha" value = "$ {senha}"/> <propriedade name = "filters" value = "stat"/> <names name = "name" (name "/" name "/" name "/" name "(names"/"name"/"name" <name "/" "20"/> <nome da propriedade = "Initialsize" = "1"/> <> <" value = "1"/> <propriedade name = "timebetweenEvictionRunsmillis" value = "60000"/> <names name = "mineVictableIdLetEmEmillis" value = "300000"/> <nome da propriedade "valuationQuery" value "/" selecione 'x' "/> (name"/"testwileIdLeidle" "True" "" "/")/")/" TestewileDle ") name = "testOnBorrow" value = "false"/> <propriedade name = "testOnReturn" value = "false"/> <names name = "poolPreparedStatements" value = "true"/> <names name = "maxpoolPreparedStatementPerConnectionSize" Value "50"/> </Bean> <inha -idango = ref = "DataSource"/> <!-Especifique o arquivo de mapeador-> <propriedade name = "mapperLocações" value = "ClassPath*: mapper/*. xml"/> </bean> <!-especificar scan Dao-> <Bean> <nome da propriedade = "BasEpackage" "" com.git.hui.demo.memo.mymymyymynyymynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynynyny- <Bean> <bean>Através da consulta on -line, existem quatro maneiras de gerenciar as coisas da primavera. Aqui estão as demonstrações uma a uma, como tocar cada método e depois ver como escolher no projeto real
Gerenciamento de coisa de programação, que percebe o gerenciamento de várias operações de banco de dados através da transaçãotemplate
um. Implementação
Então, nosso caso de transferência pode ser implementado da seguinte maneira
@RepositoryPublic CLASS Codedemo1 {@AUTOWIRED PRIVADO PARTILIDADE PARECIMENTO DO ANDER DOENDAO; @Autowired Private TransactionTemplate transactionTemplate; /** * Transfer* * @param inUserId * @param outUserId * @param payMoney * @param status 0 indicates normal transfer, 1 indicates an exception is thrown internally, 2 indicates a new thread, modify the money of inUserId + 200, 3 indicates a new thread, modify the money of outUserId + 200 */ public void transform(final int inUserId, final int outUserId, final int payMoney, final int status) {transactionTemplate.execute (new transactionCallbackwithoutResult () {vazio protegido dointransactionwithoutResult (transactionStatus transactionStatus) {moneyentity entity = moneydao. MoneyDao.IrcrementMoney (Ex -PayMoney); } // Os seguintes são todos casos de teste relacionados a testes de vazio privado (final int inuserID, final intuserID, status final int) {if (status == 1) {lança nova ilegalArgumentException ("Exceção de transferência !!!"); } else if (status == 2) {addMoney (inuserID); tente {thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); }} else if (status == 3) {addMoney (oususerID); tente {thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); }}} public void addMoney (final int userID) {System.out.printf ("AddMoney internamente:" + System.CurrentTimEmillis ()); novo thread (novo runnable () {public void run () {moneydao.incrementMoney (userID, 200); system.out.println ("sub -modifique o sucesso! agora:" + system.currenttimemillis ());}}). start (); }}Veja principalmente o método de transformação acima. O encapsulamento das coisas é realizado através da TransactionTemplate Internamente. Existem três operações de dB internamente, uma consulta e duas atualizações. A análise específica será explicada posteriormente.
O código acima é relativamente simples. A única coisa em que você precisa prestar atenção é como o feijão transactionTemplate é definido. Se você não colar o arquivo XML e os anteriores, basta colar o código -chave. Um é o TransactionManager criado com base no DataSource, e o outro é o TransactionTemplate criado com base no TransactionManager.
<!-Programando as coisas-> <bean id = "transactionManager"> <propriedade name = "DataSource" ref = "DataSource"/> </i bean> <bean id = "transactionTemplate"> <nome da propriedade = "transação
b. Casos de teste
Situação de demonstração normal, a demonstração não tem exceções e a situação de simultaneidade não é considerada
@Runwith (springjunit4classrunner.class) @ContextConfiguration ({"ClassPath*: spring/service.xml", "ClassPath*: test-datasource1.xml"}) classe pública codedemo1test {@Autowired Private CodEdemO111; @AUTowired Private Moneydao Moneydao; @Test public void testTransfor () {System.out.println ("----------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); codedemo1.transfor (1, 2, 10, 0); System.out.println ("---------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); }}A saída é a seguinte, não há problema com o dinheiro de ambas as contas
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10000
ID: 2 dinheiro = 50000
A transferência está concluída! Agora: 1526130394266
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
Uma anormalidade ocorre durante o processo de transferência, especialmente quando o cedente deduz o dinheiro e o destinatário não recebeu o dinheiro, ou seja, a situação em que o status no caso é 1.
// a exceção interna jogando @testpublic void testTransFexception () {System.out.println ("------------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); tente {codedemo1.transfor (1, 2, 10, 1); } catch (Exceção e) {e.printStackTrace (); } System.out.println ("-------------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ());}Nesse sentido, esperamos devolver o dinheiro do cedente e gerá -lo da seguinte maneira. Descobrimos que nenhum dinheiro mudou.
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
java.lang.illegalargumentException: Exceção de transferência !!!
... // omita informações de exceção
ID: 2 dinheiro = 49990
Quando o status é 2, significa que entre o dinheiro do cedente foi deduzido e o dinheiro do beneficiário não foi recebido, alguém transferiu 200 para o beneficiário. Neste momento, de acordo com o mecanismo de bloqueio do MySQL, a transferência da outra pessoa deve ser recebida imediatamente (porque a conta do beneficiário não está bloqueada) e não deve haver problema com o valor.
O resultado da saída é o seguinte:
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
## à direita está uma nota: durante o processo de transferência, o dinheiro foi depositado imediatamente e o dinheiro foi adicionado dentro não está bloqueado: 1526130827480
Sub Modify Sucesso! Agora: 1526130827500
## A transferência é concluída após economizar dinheiro! Agora: 1526130830488
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10220
ID: 2 dinheiro = 49980
Quando o status é 3, significa que o dinheiro do cedente foi deduzido e o dinheiro do beneficiário não foi recebido e alguém transferiu 200 para o cedente. No momento, como o registro e o bloqueio do cedente são adicionados, ele só pode aguardar a transferência para enviar a transferência para ter sucesso antes do sucesso de +200. Obviamente, o valor final também deve ser o mesmo.
O resultado da saída é o seguinte
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10220
ID: 2 dinheiro = 49980
## à direita está uma nota: economizei dinheiro internamente, mas não foi bem -sucedido imediatamente
## não é até a transferência ser concluída que ela é imediatamente bem -sucedida. Preste atenção à adição de dinheiro a dois registros de data e hora: 1526131101046
A transferência está concluída! Agora: 1526131104051
Sub Modify Sucesso! Agora: 1526131104053
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10230
ID: 2 dinheiro = 50170
c. Resumo
Até agora, as coisas de programação foram demonstradas em um exemplo. Do processo acima, dá às pessoas o mesmo sentimento que escrever coisas relacionadas ao SQL.
iniciar a transação;
- Esta é a lógica dentro do Método TransactionTemplate#Execute
- isto é, um conjunto de SQL que exige que as coisas sejam gerenciadascomprometer-se;
Os próximos três são o gerenciamento de coisa declarativa, que é menos usada porque cada classe de gerenciamento precisa ser adicionada a um transactionProxyFactoryBean
um. Implementação
Além de matar a transação e remover a lógica SQL interna, em comparação com a anterior, descobri que basicamente não há diferença.
classe pública FactoryBeAndemo2 {@AUTOWIRed Private Moneydao Moneydao; /** * Transfer* * @param inUserId * @param outUserId * @param payMoney * @param status 0 indicates normal transfer, 1 indicates an exception was thrown internally, 2 indicates a new thread, modify the money of inUserId + 200, 3 indicates a new thread, modify the money of outUserId + 200 */ public void transfer(final int inUserId, final int outUserId, final int payMoney, final int status) {moneyEntity entity = Moneydao.queryMoney (oususerID); if (entity.getMoney ()> PayMoney) {// você pode transferir dinheiro // reduzir o dinheiro primeiro moneydao.incrementMoney (oususerID, -PayMoney); testcase (inuserID, supersserid, status); // Adicione dinheiro a Moneydao.IncrementMoney (InUserID, PayMoney); System.out.println ("Transferência está concluída! Agora:" + System.CurrentTimemillis ()); }} private void testcase (final int inuserID, final intUSERID, status Final Int) {if (status == 1) {tiro novo ilegalArgumentException ("Exceção de transferência !!!"); } else if (status == 2) {addMoney (inuserID); tente {thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); }} else if (status == 3) {addMoney (oususerID); tente {thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); }}} public void addMoney (final int userID) {System.out.println ("Internal Add Money:" + System.currenttimemillis ()); novo thread (novo runnable () {public void run () {moneydao.incrementMoney (userID, 200); system.out.println ("sub -modifique o sucesso! agora:" + system.currenttimemillis ());}}). start (); }}O ponto principal é que precisamos configurar uma transaçãoProxyBeanFactory. Sabemos que o Beanfactory é um meio para criarmos um feijão por nós mesmos. A configuração XML relacionada é a seguinte
<!-programando coisas-> <bean id = "transactionManager"> <propriedade name = "DataSource" ref = "DataSource"/> </bean> <bean id = "FactoryBeandemo2"/> <!-Configure o proxy para a camada de negócios-> <BEAN ID = "FATORYBeanDemoMoProx. ref = "FactoryBeAndemo2" /> <!-Injete o gerenciador de transações-> <propriedade name = "transactionManager" ref = "transactionManager" /> <!-injetar as propriedades da transação-> <namesation * redoTtributes * é: a propagação da reAthAttRibutes * <borda-: propagation * namesation * reagation * reagation * é: a propagação da reAthattributes * <bornesset * é: a propagação da reAthatributes * <boration * é: a propagação da reAthatributes * <! : Quais exceções revertem transações de volta* +Exceção: Quais exceções não revertem transações de volta-> <!-essa chave corresponde aos métodos na classe de destino-> <propaganda key = "transfor"> propagation_required </sprop> <!-<propra key = "transfer"> propagation_required, readonly </prop>-<!-<!-<!-<! er
Através da configuração acima, podemos entender aproximadamente que a transaçãoProxyFactoryBean cria uma classe de proxy de fábricaBeAndemo2. Essa classe de proxy encapsula a lógica relacionada a coisas boas dentro, que podem ser consideradas uma simples abstração geral da programação anterior.
b. Teste
O código de teste é basicamente o mesmo de antes. A única diferença é que devemos usar o feijão gerado pelo BeanFactory acima, em vez de usar diretamente o FactoryBeandemo2
Caso de demonstração normal:
@Runwith (springjunit4classrunner.class) @ContextConfiguration ({"ClassPath*: spring/service.xml", "ClassPath*: test-datasource2.xml"}) factoryBeanBeandemo1test {@ResOrce (Name = "" FactoryBeanBeanBeanDemoMoMoMoMoMOMO1TEST (@ResourERC @AUTowired Private Moneydao Moneydao; @Test public void testTransfor () {System.out.println ("------------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); FactoryBeandemo2.Transfor (1, 2, 10, 0); System.out.println ("----------------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); }}Saída
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10000
ID: 2 dinheiro = 50000
A transferência está concluída! Agora: 1526132058886
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
Se o status for 1 e a exceção interna não for o caso, esperamos que não haja problemas com o dinheiro.
@Testpublic void testTransFexception () {System.out.println ("-----------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); tente {FactoryBeandemo2.Transfor (1, 2, 10, 1); } catch (Exceção e) {System.out.println (e.getMessage ()) ;; } System.out.println ("--------------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ());}A saída é
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
Transferir anormalidade !!!
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
Quando o status é 2, o resultado da análise deve ser o mesmo que acima, e a saída é a seguinte
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49950
Dinheiro interno: 1526133325376
Sub Modify Sucesso! Agora: 1526133325387
A transferência está concluída! Agora: 1526133328381
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10220
ID: 2 dinheiro = 49940
Quando o status é 3, a saída
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10220
ID: 2 dinheiro = 49940
Dinheiro interno: 1526133373466
A transferência está concluída! Agora: 1526133376476
Sub Modify Sucesso! Agora: 1526133376480
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10230
ID: 2 dinheiro = 50130
c. Resumo
A idéia do transactionProxyFactoryBean é usar o modo proxy para implementar o gerenciamento de coisas, gerar uma classe de proxy, interceptar métodos de destino e encapsular um conjunto de operações de SQL nas coisas; Comparado com o código rígido, não é invasivo e suporta métodos de configuração flexíveis.
As desvantagens também são óbvias, cada uma precisa ser configurada, o que é bastante complicado
A primavera tem duas características principais: COI e AOP. Para coisas assim, podemos usar a AOP para fazê -lo?
Para métodos que precisam ser ativados, interceptar, iniciar as coisas antes da execução, envie as coisas após a execução e reverte quando ocorrer uma exceção.
Nessa perspectiva, parece bastante promissor e as duas posturas a seguir são tocadas dessa maneira, de modo que a dependência do aspecto é necessária.
<Depencency> <GrupidId> org.aspectj </frugiD> <stifactId> AspectJweaver </stutifactId> <versão> 1.8.7 </versão> </dependency>
um. Implementação
A classe Java é exatamente a mesma que o segundo tipo, e apenas as mudanças XML
<!-Primeiro, adicione o namespace-> xmlns: tx = "http://www.springframework.org/schema/tx" xmlns: aop = "http://www.springframework.org/schema/aoP" xsi: schemalating " http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/sringt-tx.xsdugh.xsdughwork.org/schema/tx/sringt-tx.xsdlan.xsdughwork.org/schema/tx/sringt-tx.xsdlan.xsdughwork.org/schema/tx/sringt-tx.xsdlan.xsdlan:1SDGRIRO id = "txadvice" transação-manager = "transactionManager"> <tx: atributes> <!-propagação: comportamento de propagação da transação Isolamento: transação de isolamento em nível de leitura: somente leitura) Rollback para o rollback: que expiram informações->: <s)-o nome do rollback)-que ocorreu no nome do rollback. </tx: atributos> </tx: conselhos> <!-Seção de configuração-> <aop: config> <!-Configuration Point-corte-> <aOP: Pointcut Expression = "Execution (* com.git.hui.demo.mybatis.repository.Transaction.xmldemo3. <AOP: Advisor aconselhamento-ref = "txadvice" Pointcut-ref = "Pointcut1"/> </AOP: config>
Observe a configuração acima e pense no segundo método. A idéia é quase a mesma, mas esse método é obviamente mais geral. Através da seção e do ponto de corte, um grande número de configurações pode ser reduzido.
b. Teste
@Runwith (springjunit4classrunner.class) @ContextConfiguration ({"ClassPath*: spring/service.xml", "ClassPath*: test-datasource3.xml"}) classe pública xmlbeantest {@Autowired private xmldemo3 xmlDemo; @AUTowired Private Moneydao Moneydao; @Test public void testTransfor () {System.out.println ("---------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); xmldemo.Transfor (1, 2, 10, 0); System.out.println ("----------------------"); System.out.println ("ID: 1 Money =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("Id: 2 Money =" + Moneydao.QueryMoney (2) .getMoney ()); }}Este teste não é diferente do método de escrita geral e é mais simples que o método de injeção do segundo fábrica
Saída normal
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10000
ID: 2 dinheiro = 50000
A transferência está concluída! Agora: 1526135301273
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
status = 1 Quando ocorre uma exceção, a saída é
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
Transferir anormalidade !!!
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
Status = 2 O cenário de economizar dinheiro durante o processo de transferência, a saída é consistente com as expectativas anteriores.
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10010
ID: 2 dinheiro = 49990
Dinheiro interno: 1526135438403
Sub Modify Sucesso! Agora: 1526135438421
A transferência está concluída! Agora: 1526135441410
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10220
ID: 2 dinheiro = 49980
A saída de status = 3 é consistente com as expectativas anteriores
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10220
ID: 2 dinheiro = 49980
Dinheiro interno: 1526135464341
A transferência está concluída! Agora: 1526135467349
Sub Modify Sucesso! Agora: 1526135467352
--------------------------------------------------------------------------------------------------------------------------------------------------
ID: 1 dinheiro = 10230
ID: 2 dinheiro = 50170
Isso é para eliminar o XML e usar as anotações para fazê -lo, que é substituir a configuração no XML anterior pela anotação @Transactional.
um. Implementação
@RepositoryPublic Classe Annodemo4 {@AUTOWIRed Private Moneydao Moneydao; /** * Transfer * * @param inuserID * @param ultuserID * @param paymoney * @param status 0 indica transferência normal, 1 indica uma exceção é lançada internamente, 2 indica um novo encadeamento, modificar o dinheiro de inuserid + 200, 3 indica um novo encadeamento no dinheiro da saída de utensílios + 200 * * * * * * * * * * * Nível de isolamento ReadOnly: somente leitura* RollbackFor: Que exceções ocorreram Norollbackfor: que exceções ocorreram para não reverter* rollbackForClassName Rollback de acordo com o nome da classe de exceção*/ @Transaction (Propagation = propagation.Required, isolation = isolation.DerDid, Readernly = False) Final Int Status) {MoneyEntity entity = Moneydao.QueryMoney (ULUSERID); if (entity.getMoney ()> PayMoney) {// você pode transferir dinheiro // reduzir o dinheiro primeiro moneydao.incrementMoney (oususerID, -PayMoney); testcase (inuserID, supersserid, status); // Adicione dinheiro a Moneydao.IncrementMoney (InUserID, PayMoney); System.out.println ("Transferência está concluída! Agora:" + System.CurrentTimemillis ()); }} private void testcase (final int inuserID, final intUSERID, status Final Int) {if (status == 1) {tiro novo ilegalArgumentException ("Exceção de transferência !!!"); } else if (status == 2) {addMoney (inuserID); tente {thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); }} else if (status == 3) {addMoney (oususerID); tente {thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); }}} private void addMoney (final int userID) {System.out.println ("Inside Add Money:" + System.currenttimemillis ()); novo thread (novo runnable () {public void run () {moneydao.incrementMoney (userID, 200); system.out.println ("sub -modifique o sucesso! agora:" + system.currenttimemillis ());}}). start (); }}Portanto, é necessário configurá -lo em XML para permitir a anotação das coisas
<!-Programação de coisas-> <bean id = "transactionManager"> <propriedade name = "DataSource" ref = "DataSource"/> </shean> <tx: transação orientada por anotação-manager = "transactionManager"/>
Isso deixa mais claro. Em projetos reais, os métodos de XML e anotação também são os cenários mais usados.
b. Caso de teste
É exatamente o mesmo que o terceiro caso de teste, e o resultado da saída é o mesmo, e é omitido diretamente
O acima fala sobre quatro maneiras de usar as coisas na primavera. Entre eles, o método codificado pode ser o melhor entendimento, que é equivalente a traduzir diretamente o método de usar as coisas no SQL no código Java correspondente; e o método da FactoryBean é equivalente a tratar circunstâncias especiais e tratar cada coisa com uma classe de proxy para melhorar a função das coisas; Os dois últimos princípios são quase implementados usando a notificação de coisas (AOP) para definir pontos tangentes e informações relacionadas.
Programação:
transactionTemplate#execute MethodProxy BeanFactory:
Configuração XML:
Método de anotação:
tx:annotation-driven transaction-manager="transactionManager"/>documento
Quatro maneiras de gerenciamento de transações de primavera
Código -fonte
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.