Day43
service事务
问题:加钱不减钱,减钱不加钱 要在同一个事务中
经过分析发现,我们在转账的过程中,要么扣钱不加钱,要么加钱不扣钱,原因是我们执行了两次update操作
但是每次update都会开启一个新的连接,也就是新的事务,导致两次操作不在同一个事务中
要解决这个问题,就必须让他们在同一个事务中,也就是在同一个连接中
也就是说update方法内部不能开启单独的连接
问题来了:不开启单独的连接就不能创建statement
解决方法:
-
我们发现其实就是在不同类或对象之间共享数据,也就是共享连接可以通过传递参数的方式解决,参数中传入Connection对象,在service中获取了一个连接对象,开启事务 提交和回滚事务,同时在dao中接收了一个连接,(这样会导致每个dao方法都需要传递一个连接,会导致污染问题)
-
在查询时发现除了sql语句和要查询参数不同,其余相同,我们将其封装为DBUtils工具类,将参数(sql语句,要查询参数[放到数组中,从数组中拿],mapper对象(是一个接口,传递的是实现类))得到,就可以直接调用了
-
不管查询什么表,在执行查询之前都是一样的,无非就是具体怎么处理,接口实现类,实现接口作为参数传入
-
-
利用线程对象解决,我们利用静态变量,比如找一个静态map,把连接放进去,用的时候再取,我们只需要知道放的key是什么,在不同的线程中不能使用同一个key,避免不同线程获取到了同一个connection,引入
ThreadLocal<Connection> -
优化线程对象解决办法
-
现有问题:事务开启,提交,回滚代码都写到service中,service主要的职责是模拟现实业务功能
-
解决:对事物封装,将开启事务,提交,回滚等方法封装在工具类中
-
三层架构
习惯性分三层,界面层,业务逻辑层,数据访问层
- 表示层(UI Main):用户输入数据,调用业务逻辑层,展示数据或操作结果
- 业务层(Service):开启事务,调用DAO层,处理数据,提交或回滚
- 数据访问层(DAO):查询相关业务数据,根据相关业务修改数据
搭建项目(项目具体分层)
- utils:存放工具类(DBUtils)
- entity:存放实体类,javaBean等,有时用pojo表示
- dao:存放DAO接口,存放DAO接口实现类
- service:存放service接口,存放service接口实现类
- view:存放程序启动类,依情况可以编写test测试类;主要用于存放启动类,内含主方法,是程序的主入口
数据库连接池(Druid)和DbUtils
数据库连接池
- 我们每次使用的时候都需要频繁创建连接,用完关闭连接,实际上连接是不需要关闭的,可以反复使用
- 问题:频繁创建连接会导致大量的时间资源开销
- 解决:利用池化技术,用空间换取时间,通过浪费一定的空间来减少时间资源的开销
DbUtils
- Apache提供对JDBC简单封装的开源工具类库
- 核心内容
- DbUtils类:启动类
- ResultSetHandler接口:转换类型接口,以下是它的实现类
- BeanHandler:把一条记录转换成对象
- BeanListHandler:把多条记录转换成List集合
- ScalarHandler:适合获取一行一列的数据
开发步骤
- 添加依赖包(lib)---> 数据库连接 德鲁伊 DbUtils
- 编写数据库配置文件(properties)
- utils层->编写工具类 ps:一般超过两次重复就要考虑
- 利用数据库连接池 获取连接 连接池只有一个,放外面,声明静态
- 使用ThreadLocal解决事务问题
- 读取配置文件
- 获取连接 用完close(注意:这里是将连接放回连接池中)
- 事务处理:开启,提交,回滚,释放
- 分层设计
- dao层:(处理数据)接口,接口实现类
- add QueryRunner 需要一个getDataSource 从utils的工具类中创建一个
- 查询 参数1:sql语句 参数2: resultsethandler 返回结果的处理器,相当于前面的mapper对象,是一个接口
- entity层:实体层,存放get-set方法,数据库属性(idea可自动生成)
- service层:(处理具体业务)接口,接口实现类
- test层:测试,程序主入口
- dao层:(处理数据)接口,接口实现类
对于事务处理 需要管理事务 传参,否则不需要传参
自己了解一下JUnit
未完待续...

浙公网安备 33010602011771号