Prefacio
Este artículo registra principalmente cómo Spring admite las cosas y cómo puede simplemente implementar las funciones de las cosas de la base de datos cuando Spring combina mybatis. No diré mucho al respecto a continuación, echemos un vistazo a la introducción detallada juntos.
Case1: Las cosas apoyan la situación en dos tablas
Primero prepare dos tablas, una mesa de usuario y una tabla de cuentos, la estructura es la siguiente.
CREATE TABLE `user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL DEFAULT '' COMMENT 'Username', `pwd` varchar(26) NOT NULL DEFAULT '' COMMENT 'password', `isDeleted` tinyint(1) NOT NULL DEFAULT '0', `created` varchar(13) NOT NULL DEFAULT '0', `updated` varchar (13) no nulo predeterminado '0', clave primaria (`id`), clave` name` (`name`)) motor = innodb default Charset = utf8mb4; create tabla` story` (`id` int (11) no firmed no null auto_increment,` userId` int (20) no firme no indignado '0' comman 'comment' autor 'userid', `name ',` name `name` name `name` name `20). '' COMMENT 'Author', `title` varchar(26) NOT NULL DEFAULT '' COMMENT 'password', `story` text COMMENT 'Story content', `isDeleted` tinyint(1) NOT NULL DEFAULT '0', `created` varchar(13) NOT NULL DEFAULT '0', `updated` varchar(13) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `userId` (`userId`)) Motor = innodb predeterminado charset = utf8mb4;
Nuestra situación es que cuando el usuario modifica el nombre, los nombres de ambas tablas deben modificarse juntos y no se permiten inconsistencias.
Case2: soporte de una sola tabla
Transferir dinero, un usuario reduce el dinero, otro usuario aumenta el dinero
CREATE TABLE `money` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL DEFAULT '' COMMENT 'Username', `money` int(26) NOT NULL DEFAULT '0' COMMENT 'money', `isDeleted` tinyint(1) NOT NULL DEFAULT '0', `created` varchar(13) NOT NULL DEFAULT '0', `updated` varchar(13) No nulo predeterminado '0', clave primaria (`id`), clave` name` (`name`)) motor = innodb default charset = utf8mb4;
En comparación con el caso anterior, esto es más simple. Los siguientes ejemplos se explican principalmente en base a esto. En cuanto a Case1, se deja expandirse.
Primero, implementa el DAO y la entidad correspondientes
@DATAPublic de clase MoneyEntity implementa serializable {private estático final Long SerialVersionUid = -70747888842783160025l; ID privado int; nombre de cadena privada; Private int dinero; privado intsdeleted; private int creado; private int actualizado;} interfaz pública MoneyDao {MoneyEntity QueryMoney (@param ("id") int userId); // Agregar dinero, cuando sea negativo, significa reducir el dinero intEl archivo mapper correspondiente es
<? xml versión = "1.0" encoding = "utf-8"?> <! Doctype mapper public "-// mybatis.org//dtd mapper 3.0 // en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper Namespace = "com.git.hui.demo.mybatis.mapper.moneydao"> <sql id = "MoneyEntity"> id, `name`,` Money`, `isDeleted`,` creado ', `actualizado' </sql> <Select id =" QueryMoney " resultType = "com.git.hui.demo.mybatis.entity.moneyEntity"> Seleccione <incluido refid = "MoneyEntity"/> del dinero donde id =#{id} </select> <update id = "incrementMoney"> Actualizar el dinero establecido = dinero +#{addMoney} Where id =#{id} </update> </mApper>La configuración correspondiente de la fuente de datos de conexión de MyBatis
<Bean> <Property name = "ubicaciones"> <valor> classpath*: jdbc.properties </value> </prown> </bean> <bean id = "dataSource" init-method = "init" destruye-method = "cierre"> <Property Name = "DriverClassNeSnEn name = "username" value = "$ {username}"/> <propiedad name = "contraseña" valor = "$ {contraseña}"/> <propiedad name = "filters" value = "stat"/> <propiedad name = "maxactive" value = "20"/> <Property name = "inicial" valor = "1"/> <name de propiedad = "name =" mAxwait "value =" 60000 "/> <> <serper valor = "1"/> <propiedad name = "TimeBetweeVictionRunsMillis" value = "60000"/> <Property Name = "mineVictableDletEmillis" value = "300000"/> <Property name = "ValidationQuery" Value = "Seleccionar 'x'"/> <propiedad de propiedad = "Testwhileidle" Value = "verdadero"/> <Property Name = "TestOnBorrow" Value " name = "testOnBorrow" value = "false"/> <propiedad name = "testOnreturn" value = "false"/> <Property name = "PoolPreparedStatements" value = "true"/> <Property Name = "MaxPoolPreparedStatEmentPonConnectionsize" Value = "50"/> </bean> <bean id = "sqlSessionFactory"> <sperty name = "dataSource" rehiate "" refle "" "DataSource"/"refleing" "" "Dataurce" "" DataSource "" "" DataSource "/" Dataurce "" "DataSource"/"Dataurce" "DataSource" <!-Specify Mapper File-> <Property name = "mapperLocations" value = "classpath*: mapper/*. Xml"/> </bean> <!-Especify Scan Dao-> <Bean> <Property Name = "BasePackage" Value = "com.git.hui.demo.mybatis"/> <//> </> <//> <//> <//> <///0A través de la consulta en línea, hay cuatro formas de administrar las cosas de primavera. Aquí hay demostraciones uno por uno, cómo jugar cada método y luego ver cómo elegir en el proyecto real
Programación de gestión de cosas, que se da cuenta de la gestión de múltiples operaciones de DB a través de TransactionTemplate
a. Implementación
Luego, nuestro caso de transferencia se puede implementar de la siguiente manera
@RepositoryPublic CodeDEMO1 {@aUtowired private Moneydao MoneyDao; @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 estado) {transaccionTemplate.exCute (new TransactionCallBackWitHoUtResult () {protegido void dointransactionwithoUtresult (transaccionStatus transactionStatus) {MoneyEntity entity = MoneyDao.QueryMoney (outUserid); if (entity.getMoney ()> paymoney) {// puede transferir dinero /////////////OutUsid); if (entity.getMoney ()> paymoney) {// puede transferir dinero //////////////OutUsid); If (entity.getMoney ()> paymoney) {// puede transferir Money // Rede MoneyDao.incrementMoney (OutuserID, -PayMoney); } // Los siguientes son todos los casos de prueba relacionados Private void testcase (final int inuserid, final int outUserID, final int status) {if (status == 1) {throw New IlegalArgumentException ("¡Excepción de transferencia!"); } else if (status == 2) {addMoney (inuserID); intente {Thread.sleep (3000); } catch (InterruptedException e) {E.PrintStackTrace (); }} else if (status == 3) {addMoney (outUserID); intente {Thread.sleep (3000); } catch (InterruptedException e) {E.PrintStackTrace (); }}} public void addMoney (final int userId) {system.out.printf ("internamente addMoney:" + system.currentTimemillis ()); new Thread (new Runnable () {public void run () {MoneyDao.IncrementMoney (UserId, 200); System.out.println ("Sub modifica el éxito! Ahora:" + System.CurrentTimemillis ());}}). Start (); }}Mire principalmente el método de transformación anterior. La encapsulación de las cosas se realiza a través de TransactionTemplate internamente. Hay tres operaciones de DB internamente, una consulta y dos actualizaciones. El análisis específico se explicará más adelante.
El código anterior es relativamente simple. Lo único a lo que debe prestar atención es cómo se define el bean TransactionTemplate. Si no peza el archivo XML y el anterior, simplemente pegue el código de clave. Uno es el TransActionManager creado en función de DataSource, y el otro es la placa de transacción creada basada en TransactionManager.
<
b. Casos de prueba
Situación de demostración normal, la manifestación no tiene excepciones, y la situación de concurrencia no se considera
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration ({"classpath*: spring/servicio.xml", "classpath*: test-dataSource1.xml"}) clase pública codedemo1test {@aUtowired private codedemo1 codedemo1; @Autowired Private Moneydao Moneydao; @Test public void testtransfor () {System.out.println ("----------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); codedemo1.transfor (1, 2, 10, 0); System.out.println ("-----------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); }}El resultado es el siguiente, no hay problema con el dinero de ambas cuentas
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10000
ID: 2 dinero = 50000
¡La transferencia se completa! Ahora: 1526130394266
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
Se produce una anormalidad durante el proceso de transferencia, especialmente cuando el cedente ha deducido el dinero y el destinatario no ha recibido el dinero, es decir, la situación en la que el estado en el caso es 1.
// La excepción interna lanzando @TestPublic Void testTransforeException () {System.out.println ("----------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); intente {codedemo1.transfor (1, 2, 10, 1); } catch (Exception e) {E.PrintStackTrace (); } System.out.println ("---------------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 dinero =" + moneydao.querymoney (2) .getMoney ());}En este sentido, esperamos devolver el dinero del transferidor y generarlo de la siguiente manera. Descubrimos que ninguno de los dinero ha cambiado.
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
java.lang.illegalargumentException: ¡Excepción de transferencia!
... // omitir información de excepción
ID: 2 dinero = 49990
Cuando el estado es 2, significa que entre el dinero del cedente se ha deducido y no se ha recibido el dinero del beneficiario, alguien transferido 200 al beneficiario. En este momento, de acuerdo con el mecanismo de bloqueo de MySQL, la transferencia de la otra persona debe recibirse de inmediato (porque la cuenta del beneficiario no está bloqueada), y no debe haber ningún problema con la cantidad.
El resultado de salida es el siguiente:
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
## A la derecha hay una nota: durante el proceso de transferencia, el dinero se depositó de inmediato y el dinero se agregó dentro no está bloqueado: 1526130827480
Sub modifica el éxito! Ahora: 1526130827500
## La transferencia se completa después de ahorrar dinero! Ahora: 1526130830488
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10220
ID: 2 dinero = 49980
Cuando el estado es 3, significa que el dinero del cedente se ha deducido y el dinero del beneficiario no se ha recibido, y alguien transferido 200 al transferidor. En este momento, debido a que se agregan el registro y el bloqueo de escritura del transferidor, solo puede esperar a que la transferencia envíe la transferencia al éxito antes del éxito +200. Por supuesto, la cantidad final también debe ser la misma.
El resultado de la salida es el siguiente
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10220
ID: 2 dinero = 49980
## a la derecha es una nota: ahorré dinero internamente, pero no tuvo éxito inmediatamente
## No es hasta que se complete la transferencia que es inmediatamente exitoso. Preste atención a agregar dinero a dos marcas de tiempo: 1526131101046
¡La transferencia se completa! Ahora: 1526131104051
Sub modifica el éxito! Ahora: 1526131104053
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10230
ID: 2 dinero = 50170
do. Resumen
Hasta ahora, las cosas de programación se han demostrado en un ejemplo. Del proceso anterior, le da a las personas la misma sensación que escribir cosas relacionadas con SQL.
Iniciar transacción;
- Esta es la lógica dentro del método de ejecución de#Ejecutar TransactionTemplate
- es decir, un conjunto de SQL que requiere que se manejaran las cosascomprometerse;
Los siguientes tres son la gestión de las cosas declarativas, que se usa menos porque cada clase de gestión de cosas debe agregarse a una transacciónproxyFactoryBean
a. Implementación
Además de matar la plantilla de transacción y eliminar la lógica SQL interna, en comparación con la anterior, descubrí que básicamente no hay diferencia.
Public Class 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 estado) {Entidad MoneyEntity = MoneyDao.QueryMoney (OutUserID); if (entity.getMoney ()> payMoney) {// Puede transferir dinero // reducir el dinero First Moneydao.IncrementMoney (outUserID, -payMoney); TestCase (inuserid, outuserid, estado); // Agregar dinero a Moneydao.IncrementMoney (inuserid, paymoney); System.out.println ("¡La transferencia se completa! Ahora:" + System.CurrentTimemillis ()); }} Private void testcase (final int inuserid, final int outUserID, final int status) {if (status == 1) {throw New IlegalArGumentException ("¡Excepción de transferencia!"); } else if (status == 2) {addMoney (inuserID); intente {Thread.sleep (3000); } catch (InterruptedException e) {E.PrintStackTrace (); }} else if (status == 3) {addMoney (outUserID); intente {Thread.sleep (3000); } catch (InterruptedException e) {E.PrintStackTrace (); }}} public void addMoney (final int userId) {system.out.println ("interno add dinero:" + system.currentTimemillis ()); new Thread (new Runnable () {public void run () {MoneyDao.IncrementMoney (UserId, 200); System.out.println ("Sub modifica el éxito! Ahora:" + System.CurrentTimemillis ());}}). Start (); }}El punto clave es que necesitamos configurar una transacción ProfyBeanFactory. Sabemos que BeanFactory es un medio para que creemos un frijol por nosotros mismos. La configuración XML relacionada es la siguiente
< ref = "factoryBeandemo2" /> <!-inyect the Transaction Manager-> <Property Name = "TransActionManager" ref = "TransActionManager" /> <!-Inyect las propiedades de la transacción-> <Property Name = "TransactionATtributes"> <props> <!-Format de prop Prop: * Propagation: Transaction Propagation Behavie ¿Qué excepciones recolectan transacciones* +Excepción: qué excepciones no vuelven a revelar las transacciones-> <!-esta clave corresponde a los métodos en la clase de destino-> <prop key = "transfor"> propagation_required </prop> <!-<prot key = "transferir"> propagation_required, readonly </prop>-> <!-<propiLE <
A través de la configuración anterior, podemos comprender aproximadamente que TransactionProxyFactoryBean crea una clase proxy de FactoryBeandemO2. Esta clase proxy encapsula la lógica relacionada con las cosas buenas en el interior, que puede considerarse como una simple abstracción general de la programación anterior.
b. Prueba
El código de prueba es básicamente el mismo que antes. La única diferencia es que debemos usar el frijol generado por la factura de beanfactory anterior, en lugar de usar factorybeandemo2
Caso de demostración normal:
@RunWith (SpringJunit4ClassRunner.class) @ContextConfiguration ({"classpath*: Spring/Service.xml", "classpath*: test-dataSource2.xml"}) public class FactoryBeanDemo1test {@resource (name = "FactoryBeanDemoProxy") privado FactoryBeanDemo2222 FactoryBeandemo2; @Autowired Private Moneydao Moneydao; @Test public void testtransfor () {System.out.println ("--------------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); FactoryBeandemo2.transfor (1, 2, 10, 0); System.out.println ("------------------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); }}Producción
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10000
ID: 2 dinero = 50000
¡La transferencia se completa! Ahora: 1526132058886
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
Si el estado es 1 y la excepción interna no es el caso, esperamos que no haya ningún problema con el dinero.
@TestPublic void testTransforeCception () {System.out.println ("---------------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); intente {factorybeandemo2.transfor (1, 2, 10, 1); } capt (excepción e) {system.out.println (e.getMessage ()) ;; } System.out.println ("--------------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 dinero =" + moneydao.querymoney (2) .getMoney ());}La salida es
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
Transferencia de anormalidad !!!
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
Cuando el estado es 2, el resultado del análisis debe ser el mismo que el anterior, y la salida es la siguiente
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49950
Dinero interno: 1526133325376
Sub modifica el éxito! Ahora: 1526133325387
¡Se completa la transferencia! Ahora: 1526133328381
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10220
ID: 2 dinero = 49940
Cuando el estado es 3, la salida
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10220
ID: 2 dinero = 49940
Dinero interno: 1526133373466
¡La transferencia se completa! Ahora: 1526133376476
Sub modifica el éxito! Ahora: 1526133376480
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10230
ID: 2 dinero = 50130
do. Resumen
La idea de TransactionProxyFactoryBean es usar el modo proxy para implementar la gestión de cosas, generar una clase de proxy, interceptar métodos objetivo y encapsular un conjunto de operaciones SQL en las cosas; En comparación con el código duro, no es invasivo y admite métodos de configuración flexibles.
Las desventajas también son obvias, cada una es necesario configurar, lo cual es bastante complicado
La primavera tiene dos características principales: COI y AOP. Para cosas como esta, ¿podemos usar AOP para hacerlo?
Para los métodos que deben activarse, interceptar, comenzar las cosas antes de la ejecución, enviar cosas después de la ejecución y volver a reiniciar cuando ocurre una excepción.
Desde esta perspectiva, se siente bastante prometedor, y las siguientes dos posturas se reproducen de esta manera, por lo que se necesita la dependencia del aspecto.
<Spendency> <MoupRoMID> org.spectj </groupId> <artifactId> spightJWeaver </artifactid> <versión> 1.8.7 </versión> </pendency>
a. Implementación
La clase Java es exactamente la misma que el segundo tipo, y solo el XML cambia
< http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"<los id = "txadvice" transaction-ganager = "transactionManager"> <tx: atributes> <!-propagation: transacciones propagation de comportamiento aislamiento: transacciones aislamiento nivel de lectura de lectura: lectura de reversión de lectura para: qué excepciones no han ocurrido sin-rollback-for: qué exceptions no han ocurrido tiempo de rollo: tiempo de expiración-> <tx: nombre de método propagation="REQUIRED"/> </tx:attributes></tx:advice><!-- Configuration section-><aop:config> <!-- Configuration point-cut--> <aop:pointcut expression="execution(* com.git.hui.demo.mybatis.repository.transaction.XmlDemo3.*(..))" id="pointcut1"/> <!-- Sección de configuración-> <aop: Advisor ACONSED-REF = "TXADVICE" PointCut-REF = "PointCut1"/> </aop: config>
Observe la configuración anterior y piense en el segundo método. La idea es casi la misma, pero este método es obviamente más general. A través de la sección y el punto de corte, se puede reducir una gran cantidad de configuraciones.
b. Prueba
@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration ({"classpath*: spring/servicio.xml", "classpath*: test-dataSource3.xml"}) clase pública xmlBeantest {@aUtowired private xmldemo3 xmldemo; @Autowired Private Moneydao Moneydao; @Test public void testtransfor () {System.out.println ("---------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); xmldemo.transfor (1, 2, 10, 0); System.out.println ("------------------------"); System.out.println ("id: 1 dinero =" + Moneydao.QueryMoney (1) .getMoney ()); System.out.println ("id: 2 mony =" + Moneydao.QueryMoney (2) .getMoney ()); }}Esta prueba no es diferente del método de escritura general, y es más simple que el método de inyección de la segunda fábrica.
Salida normal
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10000
ID: 2 dinero = 50000
¡La transferencia se completa! Ahora: 1526135301273
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
estado = 1 Cuando ocurre una excepción, la salida es
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
Transferencia de anormalidad !!!
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
Estado = 2 El escenario de ahorro de dinero durante el proceso de transferencia, la producción es consistente con las expectativas anteriores.
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10010
ID: 2 dinero = 49990
Dinero interno: 1526135438403
Sub modifica el éxito! Ahora: 1526135438421
¡La transferencia se completa! Ahora: 1526135441410
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10220
ID: 2 dinero = 49980
La salida del estado = 3 es consistente con las expectativas anteriores
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10220
ID: 2 dinero = 49980
Dinero interno: 1526135464341
¡La transferencia se completa! Ahora: 1526135467349
Sub modifica el éxito! Ahora: 1526135467352
----------------------------------------------------------------------------------------------------------------------------
ID: 1 dinero = 10230
ID: 2 dinero = 50170
Esto es para eliminar el XML y usar anotaciones para hacerlo, que es reemplazar la configuración en el XML anterior con la anotación @Transactional.
a. Implementación
@RepositoryPublic Class Annodemo4 {@aUtowired private Moneydao MoneyDao; /** * 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 * * * attribute propagation in Transactional annotation: transaction propagation behavior isolation: transaction Nivel de aislamiento Readonly: solo lectura* Rollbackfor: qué excepciones han ocurrido Norollback para: qué excepciones han ocurrido para no revertir* reversión de reversión PayMoney, estado final int) {Entidad MoneyEntity = MoneyDao.QueryMoney (OutUserID); if (entity.getMoney ()> payMoney) {// Puede transferir dinero // reducir el dinero First Moneydao.IncrementMoney (outUserID, -payMoney); TestCase (inuserid, outuserid, estado); // Agregar dinero a Moneydao.IncrementMoney (inuserid, paymoney); System.out.println ("¡La transferencia se completa! Ahora:" + System.CurrentTimemillis ()); }} Private void testcase (final int inuserid, final int outUserID, final int status) {if (status == 1) {throw New IlegalArGumentException ("¡Excepción de transferencia!"); } else if (status == 2) {addMoney (inuserID); intente {Thread.sleep (3000); } catch (InterruptedException e) {E.PrintStackTrace (); }} else if (status == 3) {addMoney (outUserID); intente {Thread.sleep (3000); } catch (InterruptedException e) {E.PrintStackTrace (); }}} private void addMoney (final int userId) {System.out.println ("Inside Agregar dinero:" + System.CurrentTimemillis ()); new Thread (new Runnable () {public void run () {MoneyDao.IncrementMoney (UserId, 200); System.out.println ("Sub modifica el éxito! Ahora:" + System.CurrentTimemillis ());}}). Start (); }}Por lo tanto, es necesario configurarlo en XML para habilitar la anotación de las cosas
<
Esto lo deja más claro. En proyectos reales, los métodos XML y de anotación también son los escenarios más utilizados.
b. Caso de prueba
Es exactamente lo mismo que el tercer caso de prueba, y el resultado de la salida es el mismo, y se omite directamente
Lo anterior habla sobre cuatro formas de usar las cosas en primavera. Entre ellos, el método codificado puede ser la mejor comprensión, que es equivalente a traducir directamente el método de usar las cosas en SQL en el código Java correspondiente; y el método de fábrica es equivalente a tratar circunstancias especiales y tratar cada cosa con una clase proxy para mejorar la función de las cosas; Los dos últimos principios casi se implementan utilizando la notificación de la cosa (AOP) para definir puntos tangentes e información relacionada.
Programación:
transactionTemplate#execute el métodoProxy BeanFactory:
Configuración XML:
Método de anotación:
tx:annotation-driven transaction-manager="transactionManager"/>documento
Cuatro formas de gestión de transacciones de primavera
Código fuente
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.