spring事务的传播机制
spring事务失效原因
1,数据库不支持事务:比如mysql数据库,MyISAM(马儿爱涩m)引擎不持支事务,需要使用InnoDB引擎才行
2,该类不受spring管理,使用@Transactional会失效:因为spring事务是基于aop动态代理实现的,需要从ioc容器中获取bean才能为该对象生成代理类,从而支持事务。
3,@Transactional注解下的事务方法不是public:spring源码中,获取事务属性方法时会判断是否为public,非public直接返回null
4,异常被业务代码catch时:spring catch到Throwable异常事务会进行回滚,业务代码捕获异常导致spring catch不到异常所以不回滚
5,@Transactional(rollbackFor属性配置错误:比如配置的是Error.class,但是实际异常是Exception,就不会回滚
6,同一个类中,非事务方法调用事务方法
7,事务传播属性使用错误:事务默认传播机制时required,比如需要使用required却使用了suports时
spring事务的隔离级别
⚪ DEFAULT:Spring中默认的事务隔离级别,以连接的数据库的事务隔离级别为准;
⚪ READ_UNCOMMITTED:读未提交,也叫未提交读,该隔离级别的事务可以看到其他事务中未提交的数据。该隔离级别因为可以读取到其他事务中未提交的数据,而未提交的数据可能会发生回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读;
⚪ READ_COMMITTED:读已提交,也叫提交读,该隔离级别的事务能读取到已经提交事务的数据,因此它不会有脏读问题。但由于在事务的执行中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读;
⚪ REPEATABLE_READ:可重复读,它能确保同一事务多次查询的结果一致。但也会有新的问题,比如此级别的事务正在执行时,另一个事务成功的插入了某条数据,但因为它每次查询的结果都是一样的,所以会导致查询不到这条数据,自己重复插入时又失败(因为唯一约束的原因)。明明在事务中查询不到这条信息,但自己就是插入不进去,这就叫幻读 (Phantom Read);
⚪ SERIALIZABLE:串行化,最高的事务隔离级别,它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读和幻读问题,但因为执行效率低,所以真正使用的场景并不多。
mysql的优化
1、选择合适的字段类型
2、尽量把字段设置为NOT NULL
3、使用连接(JOIN)代替子查询(Sub-Queries)
4、使用联合(UNION)代替临时表
还有一些会导致索引失效的问题:
like以%开头;
or前后有不是索引的字段时;
组合索引不是使用第一列索引;
IS NULL,IS NOT NULL,NOT,< >,!=
字段上使用函数时
mysql优化:
使用join 代替子查询
避免使用函数索引
可以用in 替换 or
不要用select *
ArrayList 与 LinkedList 的区别:
数据结构不同:ArrayList底层使用的是 动态数组,初始长度为10,每次扩容为原来的1.5倍。连续的内存存储适合做查询操作。
// 迭代器遍历 |
HashMap 底层数据结构:
HashMap底层采用的是 数组+链表 或 红黑树的方式。数组初始长度为16,负载因子0.75(就是说数组中插入的元素达到数组长度的75% 数组就会进行扩容,每次扩容为原来的2倍)。数组长度超出64,并且链表长度超出8,链表就会进行树化。 for(Map.Entry<> entry:hashMap.entrySet()){ for(Object key:hashMap.keySet()){ |
JVM
双亲委派机制
根加载器 > 扩展加载器 > 类加载器/应用程序加载器 > 自定义加载器 类加载器收到类加载的请求,会将这个请求向上委托给父类加载器去完成,一直向上委托直到根加载器。 |
双亲委派机制的作用
防止加载同一个class文件。通过委托的方式去询问父级是否已经加载过该class,如果加载过了就不需要重新加载。从而保证了数据安全。 这种方式,也保证Java核心class不被篡改,即使被篡改也不会被加载,即使被加载也不会是同一个class对象,因为不同的加载器加载同一个.class也不是同一个Class对象。这样则保证了Class的执行安全。 |
springboot自动装配原理
springboot的自动装配实际上就是从spring.factories文件中获取需要进行自动装配的类,并且生成bean对象,然后交给ioc容器管理。 springboot自动装配原理: |
mybatis中#{} 和 ${}的区别
mybaits中提供了#和$两种占位符,都是实现动态sql的方式。他们可以动态传递参数到xml文件中。#占位符等同于jdbc里面的?占位符,它相当于向PreparedStatement里的预处理语句设置参数。而PreparedStatement是预编译的,并且在设置参数时如果有特殊字符会进行自动转义。所以#占位符可以防止sql注入。 使用$方式传参,相当于直接把参数拼接到sql中,不会进行特殊处理。 #和$最大的区别就是,#是占位符,$是动态参数。而动态参数无法防止sql注入。实际开发中应该尽可能使用#,$的动态传参可以用来动态传递表名和字段名 |