数据库访问
spring为我们做了什么
-
把SQLException封装为DataAccessException,这个异常是一个RuntimeException,并且让我们能区分SQL异常的原因,例如,DuplicateKeyException表示违反了一个唯一约束;
- 我们可以针对这些特殊的异常做特殊的处理
-
申明式事务,@Transactional,spring默认在RuntimeException的情况下回滚
-
rollbackFor指定会回滚事务的类型,因为java的注释只能用Class<?> 所以Xxx.class的写法在注释中很常见
-
推荐,自定义业务异常继承Runtime,这样的异常处理不要指定回滚类型,而且语义化更明显,我们可以在这些异常中封装自己属性,最好提供一个方法,产生出一个统一返回类,而不是在统一返回类中修改我们的代码。而且这种异常不需要我们在方法层面抛出,直接交给spring来管理即可,但是注意会产生事务回滚的
-
默认事务传递级别
-
什么是事务传递,如果两个方法都有事务,一个方法调用另一个方法,他们在一个事务中吗,里面的方法如果出错了,外面的方法需要回滚吗,或者说,我们怎么控制他们是否回滚
-
默认传播级别就是REQUIRED,它的意思是,如果当前没有事务,就创建一个新事务,如果当前有事务,就加入到当前事务中执行
-
这样相当于把不断调用的方法写在了一个方法之中,要么同时成功,要么同时失败
-
SUPPORTS
:表示如果有事务,就加入到当前事务,如果没有,那也不开启事务执行。这种传播级别可用于查询方法,因为SELECT语句既可以在事务内执行,也可以不需要事务;MANDATORY
:表示必须要存在当前事务并加入执行,否则将抛出异常。这种传播级别可用于核心更新逻辑,比如用户余额变更,它总是被其他事务方法调用,不能直接由非事务方法调用; 这个其实可以由我们通过逻辑来把控
REQUIRES_NEW
:表示不管当前有没有事务,都必须开启一个新的事务执行。如果当前已经有事务,那么当前事务会挂起,等新事务完成后,再恢复执行;NOT_SUPPORTED
:表示不支持事务,如果当前有事务,那么当前事务会挂起,等这个方法执行完成后,再恢复执行;NEVER
:和NOT_SUPPORTED
相比,它不但不支持事务,而且在监测到当前有事务时,会抛出异常拒绝执行;NESTED
:表示如果当前有事务,则开启一个嵌套级别事务,如果当前没有事务,则开启一个新事务。上面这么多种事务的传播级别,其实默认的
REQUIRED
已经满足绝大部分需求,SUPPORTS
和REQUIRES_NEW
在少数情况下会用到,其他基本不会用到,因为把事务搞得越复杂,不仅逻辑跟着复杂,而且速度也会越慢。 -
实现原理
- ThreadLocal,一个线程内,保存着一个事务,说明一个问题,如果不在一个线程内,是无法保证事务的,我们必须想办法把这个传递给其他线程,这样其他的线程才能加入到我们的事务中
-
-
-
-
Dao
- 很像mybatis plus 可以学习一下实现的方法
- 使用DAO简化crud
- 自己总结一下一些思想
- 如果我们的要继承的类,每次都要实现一些方法,即使这样方法的类型不同,比如泛型,都最好抽象出一层,这一层负责完成公共的部分(抽象类,实现层)
- curd这些固定的,再加上count,page等,我们完全可以用统一的模板去实现
- dao层要建立起数据和对象的对应关系,这里要注意一点,对象的字段必须全部为包装类型,包装类型的好处就是可以支持null字段,而且在对象的序列号与反序列化中,那些不能为null的基本类型,只能用0或""代替,在很多情况下,这是不合理的
其他ORM框架
-
JPA和Hibernate
- JPA是java实现数据库操作的一种规范,就像JDBC,而Hibernate是它的一种实现,就行MySQL驱动,但是Hibernate扩展了自己的方法,我们对比这些会方法,即使强大如spring,设计的接口也不一定是最好的,对比mp对条件查询的构造,我们会发现,接口的设计真的是一门艺术。
-
二级缓存,跨session缓存,这个建议最好自己实现,因为很容易导致数据不一致的问题,而且自己实现的更好一些,比如可以实现分布式共享缓存
-
Mybatis
JDBC MyBatis DataSource SqlSessionFactory Connection SqlSession - 提一下以前没有用过的获取插入后数据库自增主键值
- @Options(useGeneratedKeys = true, keyProperty = “id”, keyColumn = “id”)
- 廖老师对mybatis的使用不是很好,建议自己反复研读官网的文档
- mybatis让我们定义接口和xml,帮助我们实现这些接口,它最强大的地方在于,它的ResultMap和动态SQL
- 如果我们的动态SQL存在很复杂的or和()嵌套的情况,动态SQL和mp的条件构造器哪个更好用,我不是很清楚,但是我觉得mp的可读性更好,或许我们应该学习一下,这些复杂的条件是如何构造的
- 提一下以前没有用过的获取插入后数据库自增主键值
-
自定义orm框架
- 自己实现的orm
- 廖老师的设计还是相当厉害的,有兴趣和时间的话,可以自己实现一下
- 这里提一些自己的感悟
- 链式编程能让你的代码更简单,更优雅
- 其实SQL都是一个关键字,跟上几个关键字,比如where,比如limit,我们完全可以借助这个思想,弄一个支持多表查询的orm框架
- 还是那句话,接口的设计,真的是一门艺术
- 这里提一些自己的感悟