1、事务在什么情况下会失效?
1.访问权限问题
事务方法需要定义public,非public方法事务会失效。
2.方法被final修饰
事务底层使用了aop,那么也就是说通过jdk或者是cglib生成代理类,在代理类中实现的事务的功能,如果说方法是final修饰的了,那么就会导致代理类中无法重写该方法,从而导致添加事务失败。同样的如果是static的修饰的话也是无法通过动态代理变成事务方法。
3.方法内部调用
简单来说就是一个方法内部调用另一个方法,但是另一个方法是有事务的,这样也会导致事务失效,因为这个调用的是this对象的方法,而不是另一个方法持有的对象。
4.未被spring事务管理
这里需要明确一个前提,就是使用spring事务的前提,就是对象要被spring管理就需要创建bean实例,在开发中,我们都是通过@Controller,@Service,@Component,@Repository等注解自动的实现依赖注入实例化的功能,但假如说在相应的控制层,业务层,数据层忘记加相应的注解,那么也是会失效的。
5.多线程调用
接着附上伪代码进行讲解:
@Slf4j
@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.doOtherThing();
}).start();
}
}
@Service
public class RoleService {
@Transactional
public void doOtherThing() {
System.out.println("保存role表数据");
}
}
事务add方法中调用了另一个事务doOtherThing,但是事务方法是在另一个线程中调用的,这样就会导致两个方法不在同一个线程中,获取到的数据库链接不一样,是两个不同的事务,一旦doOtherThing发生异常,add方法也是不可能发生回滚的.这里需要解释以下什么是同一个事务,也就是说只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务。
6.错误的传播特性
在使用@Transactional注解时,是可以指定propagation参数的,该参数是用来指定事务的传播特性,其中只有required,requires_new,nested这三种才会创建新事务。Propagation.NEVER这种类型的传播特性不支持事务,如果有事务则会抛异常。
7.自己吞了异常
把异常放到try代码块中捕获了手动抛出的异常。使用try捕获异常后,Spring的事务管理将不会捕获到你手抛的异常,因为你使用了try捕获捕获异常,Spring会默认你已经处理了异常,不需要它进行异常的处理了。因此不能使用try.捕获异常。
@Slf4j
@Service
public class UserService {
@Transactional
public void add(UserModel userModel) {
try {
throw new RuntimeException();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
8.手动抛了别的异常
spring只会对RuntimeException进行处理,如果手抛了其它异常,spring是不会进行处理的。
Slf4j
@Service
public class UserService {
@Transactional
public void add(UserModel userModel) throws Exception {
try {
saveData(userModel);
updateData(userModel);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new Exception(e);
}
}
}
2、怎么用Sql语句复制另一张表?
1、复制表结构及数据到新表
CREATE TABLE 新表 SELECT * FROM 旧表
2、只复制表结构到新表
CREATE TABLE 新表 SELECT * FROM 旧表 WHERE 1=2
或CREATE TABLE 新表 LIKE 旧表
3、复制旧表的数据到新表(假设两个表结构一样)
INSERT INTO 新表 SELECT * FROM 旧表
4、复制旧表的数据到新表(假设两个表结构不一样)
INSERT INTO 新表(字段1,字段2,…) SELECT 字段1,字段2,… FROM 旧表
5、可以将表1结构复制到表2
SELECT * INTO 表2 FROM 表1 WHERE 1=2
6、可以将表1内容全部复制到表2
SELECT * INTO 表2 FROM 表1
3、数据库连表查询,左外联,右外联,内联查的区别?
INNER JOIN(内联):两个表a,b 相连接,取出符合连接条件的字段
LEFT JOIN(左联):先返回左表的所有行,再加上符合连接条件的匹配行
RIGHT JOIN(右联):先返回右表的所有行,再加上符合连接条件的匹配行
4、sql语句过慢怎么定位问题?
参考一下文章:MySQL性能分析工具——如何快速定位SQL执行慢的原因?_warybee的博客-CSDN博客_mysql慢sql分析工具
5、说一下JDBC在连接数据库的操作上几个步骤?
1、获取驱动
Class.forName("驱动全限定名")
全限定名=包名+类名
2、配置url、use、password
url:协议名:子协议名//host:port/数据库名
use:用户名
password:密码
3、使用drivermanager创建connection对象
Connection conn=DriverManager.getConnection();
6、Like 后 加% 和 加_ 的区别在哪里?
-
%百分号通配符:表示任何字符出现任意次数(可以是0次).
-
_下划线通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符.
示例:
该语句匹配所有以Li开头的名字。
SELECT *FROM products WHERE products.prod_name like 'Li%';
该语句仅能匹配Lix之类的名字。
SELECT FROM products WHERE products.prod_name like 'Li_';
持续更新中,敬请期待!
Spring第51篇:事务失效常见的几种原因_chenzoff的博客-CSDN博客
如何用sql语句复制一张表_大楠树的博客-CSDN博客_sql 复制表
数据库中的左外连接右外连接和内连接的区别?_零点_java的博客-CSDN博客_数据库左右连接的区别数据库内联、左联和外联的区别_aogogogo的博客-CSDN博客_内联和外联的区别数据库中的左外连接右外连接和内连接的区别?_零点_java的博客-CSDN博客_数据库左右连接的区别
https://www.jb51.net/article/39435.htm
SQL为什么慢,如何定位处理?_ Mike.磊的博客-CSDN博客_如何定位慢sql
MySQL性能分析工具——如何快速定位SQL执行慢的原因?_warybee的博客-CSDN博客_mysql慢sql分析工具 如何使用性能分析工具定位SQL执行慢的原因? - 知乎