Razones del fracaso de la transacción de primavera

1 El motor de base de datos no admite transacciones.

Las transacciones de Spring son transacciones de la capa empresarial y su capa inferior aún depende del soporte de transacciones de la propia base de datos. Tomando MySQL como ejemplo, su motor MyISAM no admite operaciones de transacciones, InnoDB es el motor que admite transacciones, InnoDB se usa generalmente para admitir transacciones.

2 clases no son administradas por Spring

Como se muestra en el siguiente ejemplo:

//@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑    
    }
}

Si comenta la anotación en este momento @Service, esta clase no se cargará en un Bean, entonces esta clase no se Springadministrará y la transacción no será válida.

3 El método no es público.

@TransactionalSolo se puede usar publicen métodos; de lo contrario, la transacción no se invalidará. Si desea usarlo en otros publicmétodos, puede activar AspectJel modo proxy.

4 Problema de autollamada

Ejemplo 1:

@Service
public class OrderServiceImpl implements OrderService {
    
        
    public void update(Order order) {
    
            
        updateOrder(order);    
    }    
    @Transactional    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑    
    }
}

updateNo hay anotaciones en el método @Transactional , llame @Transactionalal método anotado updateOrdery updateOrderagregue una transacción al método.

Ejemplo 2:

@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void update(Order order) {
    
           
        updateOrder(order);    
    }    
    @Transactional(propagation = Propagation.REQUIRES_NEW)    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑    
    }
}

En el Ejemplo 2 , updatese agrega el método y se abre una nueva transacción.@TransactionalupdateOrderREQUIRES_NEW

En los dos ejemplos anteriores, las transacciones no tendrán efecto porque se llaman a sí mismas, es decir, llamar al método propio de la clase sin pasar por la clase proxy de Spring. De forma predeterminada, la transacción solo tendrá efecto cuando se llame externamente.

5 La fuente de datos no tiene configurado un administrador de transacciones

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    
    
    return new DataSourceTransactionManager(dataSource);
}

Como se muestra arriba, incluso si se usa la función de administración de transacciones de Spring en el código, si el administrador de transacciones de Spring no está configurado en el proyecto, la transacción de Spring no tendrá efecto.

6 transacciones no son compatibles

propagationError de configuración del comportamiento de propagación de transacciones
Ejemplo:

@Service
public class OrderServiceImpl implements OrderService {
    
        
    @Transactional    
    public void update(Order order) {
    
            
        updateOrder(order);    
    }    
    @Transactional(propagation = Propagation.NOT_SUPPORTED)    
    public void updateOrder(Order order) {
    
            
        // 业务逻辑   
    }
}

Propagation.NOT_SUPPORTED: Indica que no se ejecutará como una transacción y, si actualmente hay una transacción, se suspenderá.

Si Propagation está configurado para no admitir la ejecución en modo de transacción, la transacción no tendrá efecto.

7 Se comió anormal

Ejemplo:

@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void updateOrder(Order order) {
    
            
        try {
    
                
            // 业务代码        
        } catch {
    
    
            
        }    
    }
}

Si come la excepción y luego no la descarta, ¡la transacción no se revertirá!

8 Error de tipo de excepción

Ejemplo:

@Service
public class OrderServiceImpl implements OrderService {
    
       
    @Transactional    
    public void updateOrder(Order order) {
    
            
        try {
    
                
            // 业务代码        
        } catch {
    
                
            throw new Exception("更新错误");        
        }    
    }
}

Esta transacción no tendrá efecto porque la reversión predeterminada es: RuntimeExceptionSi desea activar la reversión de otras excepciones, debe configurarla en la anotación, como por ejemplo:
@Transactional(rollbackFor = Exception.class)
Esta configuración se limita a la clase de excepción Throwable y sus subclases.

9 La excepción ocurrió en el hilo recién creado.

@Service
public class UserService {
    
    
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleService roleService;
 
    @Transactional
    public void add(UserModel userModel) throws Exception {
    
    
        userMapper.insertUser(userModel);
        new Thread(() -> {
    
    
            // 此处发生异常
            roleService.save();
        }).start();
    }
}
@Service
public class RoleService {
    
    
    @Transactional
    public void save() {
    
    
        // 保存数据
    }
}

Podemos ver que en el método de transacción agregar, se llama al método de transacción guardar, pero el método de transacción guardar se llama en otro hilo. Esto dará como resultado que los dos métodos no estén en el mismo subproceso y obtengan conexiones de bases de datos diferentes, lo que dará como resultado dos transacciones diferentes. Si se produce una excepción en el método de guardar, es imposible revertir el método de agregar.

Supongo que te gusta

Origin blog.csdn.net/qq_41943900/article/details/133386156
Recomendado
Clasificación