前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从零开始学后端(4)——JDBC的重构设计

从零开始学后端(4)——JDBC的重构设计

作者头像
老马的编程之旅
发布2022-06-22 12:54:25
3450
发布2022-06-22 12:54:25
举报
文章被收录于专栏:深入理解Android

重构(Refactoring)就是通过调整程序代码,改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。

问题1:每个DAO方法中都会写:驱动名称/url/账号/密码,不利于维护.

如果现在我们从MySQL迁移到Oracle中去,此时就得修改每一个DAO方法的驱动名称/url/账号/密码. 解决方案:使用成员变量来表示,成员变量的作用域在整个类中有效.

问题1已经解决(通过在DAO类中定义成员变量). 问题2:我们在开放中会存在N个DAO实现类,那么此时每一个DAO实现类中都得提供连接数据库的四个基本要素的成员变量.

解决方案:现在需要完成在多个类中共享驱动名称/url/账号/密码四个信息,我们可以定义一个类(JdbcUtil),把这四个信息存储在该类中,并且使用public static修饰.

此时DAO代码:

问题3: 问题2是完美解决了,但是存在一些遗憾: 1):JdbcUtil中的四个字段应该私有化起来,体现封装. 2):其实在DAO实现类中,仅仅需要获取一个Connection对象即可,至于该对象如何创建,可以不关心.

解决方案:我们在JdbcUtil类中提供一个静态方法,用于返回Connection对象.

此时DAO代码: conn = JdbcUtil.getConn();

问题4:我们分析右图JdbcUtil类中的getConn方法的代码,发现,每次调用getConn方法都需要加载注册驱动,而我们其实就只需要在最初加载一次即可.

解决方案:在静态代码块中去加载和注册数据库驱动即可.

问题5:每一个DAO方法最后,都需要释放资源,该代码没有技术含量,又臭又长.

DML操作: 关闭Connection和Statement对象. DQL操作: 关闭Connection和Statement以及ResultSet对象.

解决方案:在JdbcUtil类中提供close方法用于关闭三个资源对象.

关闭DML操作资源:JdbcUtil.close(conn,st,null); 关闭DQL操作资源: JdbcUtil.close(conn,st,rs);

问题6:在JdbcUtil类中提供了四个字段分别表示连接数据库的四要素(驱动类名,URL,账号,密码),存在硬编码,如果需要修改连接的数据库,就只能来修改该源代码.

解决方案: 我们一般把数据库的连接信息存放到属性文件中(db.properties).

接下来再通过Properties类来加载资源文件,并读取其中的信息即可.

问题7:在DAO方法中拼接SQL语句,很恶心,稍后使用PreparedStatement解决. 问题8:在每一个DAO方法中都创建一个新的Connection对象,使用之后,就立刻释放了,也就是说没有充分利用Connection对象,而创建Connection对象的成本非常大, 问题9:DML操作模板是相同的,DQL操作模板也是相同的.

预编译语句对象

预编译语句对象 VS 静态语句对象

Statement和PreparedStatement的区别: PreparedStatement 的优点: 1).PreparedStatement 代码的可读性和可维护性. (SQL模板,使用占位符表示参数) 2).PreparedStatement 能最大可能提高性能(预编译),MySQL不支持PreparedStatement的性能优化. 3).PreparedStatement 能保证安全性. 可以防止SQL注入:演示登陆操作 选择:使用PreparedStatement.

事务管理操作

案例:银行转账:从张无忌账户上给赵敏转1000块.

准备:account(账户表):

id name(账号,唯一) balance(余额) 1 张无忌 20000

2 赵敏 0

操作步骤: 1):检查张无忌的账户余额是否大于等于1000. SELECT * FROM account WHERE name = ‘张无忌’ AND balance >= 1000; 2):从张无忌的账户余额中减少1000. UPDATE account SET balance = balance - 1000 WHERE name = ‘张无忌’; 3):再在赵敏的账户余额中增加1000. UPDATE account SET balance = balance + 1000 WHERE name = ’ 赵敏’;

如果:在第二步和第三步之间如果程序中断,怎么办? 通过异常来模拟.

代码语言:javascript
复制
事务(Transaction,简写为tx):
     在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。
     我们把多个密不可分的操作看做是一个整体,那么该整体就称之为一个事务.
--------------------------------------------------
事务的ACID属性:
1. 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 
2. 一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态,但是不最终数据不能被破坏,两个账户的总余额是不能改变的.
3. 隔离性(Isolation):MySQL再讲
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4. 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响
--------------------------------------------------
事务:指构成单个逻辑工作单元的操作集合
事务处理:保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),要么整个事务回滚(rollback)到最初状态
处理事务的两个动作:
       提交:commit:   当整个事务中,所有的逻辑单元都正常执行成功.  ---->提交事务.---数据已经提交,不能更改.
       回滚:rollback:  当整个事务中,有一个逻辑单元执行失败,              ---->回滚事务.  
                      撤销该事务中的所有操作,释放锁--->恢复到最初的状态.
代码语言:javascript
复制
1):默认情况下,在JDBC中执行DML操作就会自动提交事务,此时我们得设置事务的手动提交机制(取消事务的自动提交).
2):查询操作,不涉及数据的更改,所以不需要事务.
3):MySQL中InnoDB存储引擎支持事务,MyISAM不支持.
     alter table account engine = 'MyISAM';

意识:如果是DML操作时,没有异常,代码也正确,但是数据改变不了,首先去想到事务没有提交.

操作事务的模板:

try{
   //取消事务自动提交:
   connection对象.setAutoCommit(false);
   操作1
   操作2
   操作3     
   //提交事务
   Connection对象.commit();
}catch(Exception e){
     //处理异常
     //回滚事务
    Connection对象.rollback();
}finally{
    释放资源
}

批处理操作

代码语言:javascript
复制
批量操作(batch):当需要成批插入或者更新记录时。
可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率.

JDBC的批量处理语句包括下面两个方法:
addBatch(String sql):添加需要批量处理的SQL语句或是参数;
executeBatch();执行批量处理语句;

通常我们会遇到两种批量执行SQL语句的情况:
多条SQL语句的批量处理; :Statement
一个SQL语句的批量传参; :PreparedStatement


需求:同时向t_student表,插入5000条数据.
   在JDBC中,MySQL不支持批量操作.
-------------------------------------------------------------------------
Statement 批处理 : 一次性可以执行多条sql语句,需要编译多次。
应用场景:系统初始化 (创建表,创建数据等)
添加sql语句,st.addBatch(sql)   --添加sql语句
批量处理sql语句,int[] st.executeBatch()
清除缓存: st.clearBatch();
-------------------------------------------------------------------------
PreparedStatement 批处理 : 执行一条sql语句,编译一次,执行sql语句的参数不同。
应用场景:表数据初始化
添加批量参数:psmt.addBatch()    --添加实际参数,执行之前,需要执行psmt.setXxx()设置实际参数
执行批处理:int[] psmt.executeBatch()
清除缓存:pstm.clearBatch();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 预编译语句对象
  • 预编译语句对象 VS 静态语句对象
  • 事务管理操作
  • 准备:account(账户表):
  • 2 赵敏 0
  • 批处理操作
相关产品与服务
访问管理
访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档