Transação declarativa
Artigo Diretório
1. Introdução às transações declarativas
-
Antes de precisar escrever uma transação por meio de programação complexa, agora você só precisa dizer ao Spring qual método é o método de transação, e o Spring pode controlar automaticamente a transação
-
Método de transação: as operações no método atendem às quatro características de atomicidade e outras transações (todas são executadas ou não executadas)
-
O gerenciador de transações DataSourceTransactionManager no Spring pode realizar o controle da transação quando o método de destino está sendo executado
Em segundo lugar, as etapas para usar transações declarativas
- Use c3p0 para se conectar ao banco de dados
(1) Crie o arquivo c3p0.properties no diretório src
jdbc.username=root
jdbc.password=root
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/tx?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone = GMT
jdbc.driverClass=com.mysql.jdbc.Driver
(2) Configuração em xml
<context:property-placeholder location="classpath:c3p0.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>
</beans>
(3) Teste
@org.junit.Test
public void test() throws SQLException {
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
DataSource dataSource = (DataSource)ioc.getBean("dataSource");
System.out.println(dataSource.getConnection());
//com.mchange.v2.c3p0.impl.NewProxyConnection@7d68ef40
}
- Use JdbcTemplate para operar o banco de dados
(1) Pacote guia
(2) Configuração de gravação
Existe um construtor JdbcTemplate parametrizado (DataSource dataSource) no
JdbcTemplate ; é necessário criar um objeto JdbcTemplate para operar o banco de dados, para não ir ao novo objeto, registre-o no container
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 引用容器中已经创建好的使用c3p0连接数据库的dataSource对象 -->
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
(3) Teste
@org.junit.Test
public void test2() {
//将book表中book_name为book01的书的price修改为50
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
JdbcTemplate jdbcTemplate = (JdbcTemplate)ioc.getBean("jdbcTemplate");
String sql = "UPDATE book SET price=? WHERE book_name=?";
int update = jdbcTemplate.update(sql, 50, "book01");
System.out.println("受影响的行数:" + update);
//受影响的行数:1
}
- Configure o gerenciador de transações (aspecto da transação)
(1) Pacote guia
(2) Escrito em xml
- Adicionar anotação @Transactional ao método de transação
(1) Criar BookDao
@Service
public class BookDao {
@Autowired
JdbcTemplate jdbcTemplate;
//修改账户的余额
public void updateBalance(String username, int price) {
String sql = "UPDATE account SET balance=balance-? WHERE username=?";
jdbcTemplate.update(sql, price, username);
}
//修改图书的库存
public void updateStock(int stock, String isbn) {
String sql = "UPDATE book_stock SET stock=? WHERE isbn=?";
jdbcTemplate.update(sql, stock, isbn);
}
}
(2) Criar BookService
@Service
public class BookService {
@Autowired
BookDao bookDao;
//事务方法
@Transactional
public void update(String username, int price, String isbn, int stock) {
//修改余额
bookDao.updateBalance(username, price);
//修改库存
bookDao.updateStock(stock, isbn);
int i = 10 / 0; //出现算术异常、事务方法中的两个操作均无法完成(回滚)
}
}
3. Detalhes da transação
A seguir estão os atributos na anotação @Transactional
Configuração de tempo limite de tempo limite, tipo int, se a execução do método de transação exceder a duração especificada, se não terminar, será encerrado e revertido, em segundos
用法 : @Transactional (tempo limite = 3)
- readOnly é
definido como uma transação somente leitura, tipo booleano, pode acelerar a consulta, apenas o método de transação pode ser usado para operações de consulta, se houver uma operação de modificação, um erro será relatado
用法 : @Transactional (readOnly = true)
- noRollbackFor / rollbackFor
noRollbackFor: definir algumas transações anormais que foram originalmente revertidas não podem ser revertidas
rollbackFor: definir algumas transações anormais
que originalmente não foram revertidas para permitir que elas retrocedam Ambos são do tipo classe []
Classificação de
exceção: exceção de tempo de execução: não pode ser processado em tempo de compilação e todos são revertidos por padrão.
Exceção de tempo de compilação: deve ser processado em tempo de compilação (try-catch, throws), e o padrão não é revertido
用法 : @Transactional (noRollbackFor = {NullPointerException.class, xxx.class})
transação de nível de isolamento de isolamento, tipo de isolamento
uso:
Quatro, casos espalham comportamento
-
Introdução
Se houver várias transações aninhadas, ou seja, o método de transação é chamado no método de transação, se uma das transações for anormal, quais dessas transações aninhadas serão revertidas com ela, e quais não -
Instruções
- Classificação do comportamento de comunicação
如:
(1) 使用了REQUIRED属性的事务方法如果嵌套在一个大的事务方法中,则二者属于同一个 事务线上,一个失败,另一个也跟着回滚
(2) 使用了REQUIRED_NEW属性的事务方法如果嵌套在一个大的事务方法中,则二者的事 务相互独立,一个失败,另一个不受影响(不会回滚)
- Comportamento de comunicação gráfica
No método de transação MulTx () na figura abaixo, dois métodos de transação checkout () e updatePrice () são chamados;
discuta o caso de dois métodos de transação aninhados usando atributos de diferentes comportamentos de propagação:
- ponto importante
(1) O uso de atributos como @Transactional (tempo limite = 3) para o método de transação aninhada não afetará toda a transação, e esses atributos devem ser usados na transação grande que o aninha para afetar toda a transação
(2) Se os métodos de transação desta classe estão aninhados nos métodos de transação desta classe, eles pertencem à mesma transação
Quinto, controle de transação usando configuração xml
- Configure o gerenciador de transações (aspecto da transação)
<!--
基于xml配置的事务;依赖tx名称空间和aop名称空间
1)、配置事务管理器(事务切面)
2)、配置出事务方法
3)、告诉Spring哪些方法是事务方法,事务切面按照给定的切入点表达式去切入事务方法
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务切面按照给定的切入点表达式去切入事务方法 -->
<aop:config>
<!-- 指明要切入哪些方法,但这些方法不一定使用事务 -->
<aop:pointcut expression="execution(* com.atguigu.ser*.*.*(..))" id="txPoint"/>
<!-- advice-ref指向配置事务管理器 -->
<aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"/>
</aop:config>
<!--
配置事务管理器
transaction-manager="transactionManager":指定是配置哪个事务管理器;
-->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<!--事务属性 -->
<tx:attributes>
<!-- 指明切入点表达式中的哪些方法是事务方法,-->
<tx:method name="*"/> <!-- 所有方法都加事务 -->
<tx:method name="checkout" propagation="REQUIRED" timeout="-1"/>
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>