事务:一件完整的事情,包含多个操作,要么全部成功,要么全部失败
MySQL中的事务控制:
MySQL的事务默认自动提交,一条SQL语句就是一个事务
开启手动事务方式:
方式一:关闭自动事务
方式二:手动开启一个事务
start transaction--开启一个事务
commit;事务提交
扩展:Oracle中事务默认是手动提交
Java中的事务控制:
在Connection接口的API:
setAutoCommit(false):手动开启事务
commit():事务提交
rollback():事务回滚
扩展:了解Savepoint还原点
void rollback(Savepoint savepoint)
////////////////////////////////////////////////////////////////////////////////////
在service层我们获取了connection连接,开启了事务,怎么在dao层获取同一个连接呢?
方法一:
向下传递参数connection,但是连接应该在service层释放
方法二:
可以将connection对象绑定到当前线程上
jdk中有一个ThreadLocal帮我们做到了实现
注意:ThreadLocal实例通常是类中的private static字段,它们希望与某一个线程相关联
private static ThreadLocal<Connection> tl = new ThreadLocal<>();
ThreadLocal的常用方法:
构造:new ThreadLocal()
set (T value):将内容与当前线程绑定
Object get():获取和当前线程绑定的内容
remove():将当前线程和内容解绑
源码:内部维护了一个map集合
map.put(当前线程,内容)
map.get(当前线程)
map.remove()
事务总结:
事物的特性:ACID
原子性;
一致性:事务执行前后,业务状态和其他业务状态保持一致
隔离性:一个事物执行的时候最好不要受到其他事务的影响
持久性:一旦事务提交或者回滚,状态都要持久化到数据库中
不考虑隔离性会出现读问题:
脏读:在一个事务中读取到了另一个事务中没有提交的数据
不可重复读:在一个事务中,两次查询的结果不一致(针对update操作)
幻读:在一个事务中,两次查询的结果不一致(针对insert操作)
通过设置数据库的隔离级别来避免上面的问题
MySQL默认隔离级别是repeatable read可重复读,可以避免前两类问题
开发中绝不允许脏读出现
请求转发与请求重定向使用时机:
request域没有数据用哪个都可以
有表单使用的时候,如果使用请求转发会出现重复提交:
解决方案1:使用重定向
解决方案2:使用令牌机制实现解决重复提交问题
多条件SQL拼接查询:select ... where 1=1 这是前提格式
分页原理:
技术分析:
将数据按照页码划分,提高用户体验度
分类:
物理分页:一次只去数据库中查询当前页数据(实际开发中经常使用)
逻辑分页:一次性将所有的数据查询出来,放入内存中,按照用户点击的页码,从内存截取显示(效率高),维护起来比较麻烦
MySQL中的分頁使用关键字limit
Oracle是通过rownum关键字使用两条SQL嵌套出来的,SQL server是通过top关键字实现
理论:
从m条开始向后查询n条数据
格式1:select ... limit m,n (m+1~m+n的数据)
格式2:select ...limit n;(等价于select ... limit 0,n)
每页显示3条数据:
第一页:0,3
第二页:3,3
第三页:6,3
第n页:(n-1)*3,3
分頁需要使用的数据:
当前页内容:limit
当前页码:从前台传递
每页显示数据条数:固定
总条数 ;count(*)
总页数:总条数/每页显示的条数向上取整 Math.ceil(double) 因为是double,所以总条数x1.0
以后开发中会将这五个参数封装为Javabeen(PageBean)
这个JavaBeen的字段:显然只需要传递一个当前页码给后台即可
private List<T> list; 查询
private int currentPage; 前台传递
private int pageSize; 固定
private int totalCount; 查询
private int totalPage; 计算
注:前台传递一个页码,返回值是一个PageBean实体对象