JDBC精讲---第二阶段

一 . 什么是DAO层 ?

1 . DAO(Data Access Object)是指数据库访问接口 , 是一个封装了对数据源的访问操作的公共的API ;

二 . 什么是DRY原则 ?

1 . don ' t  repeat  yourself ! 也就是我们在编写代码的时候尽量不要编写重复的代码 !

三 . DAO的设计规范

1 . DAO组件包括 : DAO接口 , DAO实现类 , DAO测试类(严格来说DAO测试类不属于DAO组件) ;

2 . 包的命名规范 : package 域名倒写.模块名称.组件名称 ;

3 . 类名和接口命名规范 : 

    ⑴ . domain类 : 存储在domain包中 , 用于描述一个个对象 , 也就是俗称的javaBean , 包含字段和getter/setter方法 , 使用名词 , 比如Student , Employee ;

    ⑵ . dao接口 : 存储到dao包中 , 用于表示某一个对象的CRUD操作声明 ;

          命名规范 : IXxxDAO/IXxxDao , 此时的Xxx表示domain对象 ;

    ⑶ . dao实现类 : 存储到dao.impl包中 , 用于表示一个DAO接口的实现类 , 所以必须实现dao接口 ;

          命名规范 : XxxDAOImpl/XxxDaoImpl

    ⑷ . dao测试类 : 根据DAO接口来生成的 , 起名 : XxxDAOTest/XxxDaoTest , 该测试类中应该包含DAO中每一个方法的测试方法 ; 

四 . 开发步骤

1 . 先在数据库中创建对应的数据库表格 , 用以存储数据 , 例如 t_student ;

2 . 建立domain包和domain类 , 例如 Student ;

3 . 建立dao包和dao接口 , 例如 IStudentDao ;

4 . 建立dao.impl包和dao实现类 , 例如 StudentDaoImpl ;

5 . 根据Dao接口创建Dao测试类 , 例如 StudentDaoTest ;

6 . 编写StudentDaoImpl中的每一个Dao方法的实现 ;

7 . 每编写一个Dao方法的实现 , 就测试该功能是否正确 ;

五 . PreparedStatement预编译原理

1 . 对于某一些数据库服务器 , 存在着预编译语句池 , 每一条SQL语句进入DBMS的时候 , 会先判断预编译语句池中是否存在该条SQL语句 , 如果不存在的话 , 则会依次执行安全性分析 , 语法分析 , 预编译SQL语句 , 选择并执行一个计划 , 返回结果集或者受影响的行数 , 如果预编译语句池中存在该条传入的SQL语句 , 则会直接执行第四步 , 进而提高程序的执行效率 ;

2 . MySQL数据库不支持PreparedStatement预编译优化 , Oracle数据库支持 ;

六 . SQL注入攻击的原理

1 . 假设现在我们后台验证用户名和密码所使用的是Statement , 那么它将只能执行静态sql语句 , 也就是说我们肯定会定义一条用于验证用户账户名和密码的sql语句 , 例如 :

String sql = "select * from student where userName = 'abc' and password = '123'";

(下划线部分为用户在登录界面输入的账号和密码);

如果此时黑客恶意在登录框输入' or 1=1 or ' , 那么此时后台验证账号和密码的sql语句经过拼接之后就变成了 :

select * from student where userName = ' ' or 1=1 or ' ' and password = '123' ; 

这样的话 , 整句sql语句的语义也会因此改变 , 根据该sql语句 , 系统就会判定黑客登录成功 ;

2 . 如果是使用PreparedStatement , 则不会出现这种情况 , 因为加入占位符的sql语句的语义在当时就固定了 , 则不会出现上述问题 , 所以相对来说 , PreparedStatement更加安全 ;

七 . 什么是事务

1 . 事务(Transaction , 简称Tx) , 在数据库中 , 所谓事务是指一组逻辑操作 , 不论成功与失败都作为一个整体进行工作 , 要么全部成功 , 要么全部失败 ;

2 . 处理事务涉及到的两个动作 : commit和rollback ;

八 . 事务的ACID属性

1 . 原子性(Attomicity) : 事务是应用中不可再分的最小逻辑执行单位 , 要么都执行 , 要么都失败 ;

2 . 一致性(Consistency) : 事务结束后数据库内的数据是合法并且正确的 ; 

3 . 隔离性(Isolation) : 并发执行的事务之间彼此相互独立 , 互不干扰 ;

4 . 持久性(Durability) : 事务提交后 , 数据是永久性的 , 不可回滚 ;

九 . 如何在代码中处理事务

1 . 在JDBC中默认情况下 , 事务是自动提交的 , 弱项控制事务 , 必须先设置事务为手动提交 ;

    Connection对象 . setAutoCommit(false) ;

    Connection对象 . commit() ;

2 . 必须在捕获异常中回滚事务 , 因为此时虽然事务有可能没有提交 , 但由于存在同步锁的问题 , 如果不会滚事务的话 , 数据库资源得不到释放 ;

    Connection对象 . rollback() ;

3 . 在执行一个DML/DDL操作的时候 , 就已经提交事务了 ; 

4 . 针对于CRUD操作 , 只有DML才需要事务 , 查询操作不需要事务 ;

5 . MySQL中 , InnoDB引擎支持外键和事务 , MyISAM不支持外键 , 也不支持事务 ;

6 . 代码模板 :

Connection con=jdbcUtil.getConnebtion();

PreparedStatement st=null;

ResultSet rs=null;

try{

    con.setAutoCommit(false);======设置自动提交事务关闭

    ......

    con.commit();======操作代码执行完毕后提交事务

}catch(Exception e){

    e.printStackTrace();

    try{

        con.rollback();======回滚事务

    }catch(SQLException e1){

        e1.printStackTrace();

    }

}finally{

    jdbcUtil.close();

}

十 . 批处理操作

1 . MySQL数据库既不支持PreparedStatement的性能优化 , 也不支持JDBC中的批量操作 , 但是在新的JDBC驱动中 , 我们可以通过设置参数来支持批处理操作 (对PreparedStatement的批处理有效) ;

    将db . properties文件中的url选项改为 : 

    url = jdbc:mysql://location:3306/jdbcdemo?rewriteBatchedStatements=true

2 . 批量更新机制 , batch , 当需要批量插入或者更新记录时 , 可以采用Java的批量更新机制 , 这一机制允许多条语句一次性提交给数据库批量处理 , 通常情况下比单独处理更有效率 ;

3 . JDBC的批量处理语句包括下面两个方法 : 

    addBatch(String) : 添加需要批量处理的SQL语句或是参数 ;

    executeBatch() : 执行批量处理语句 ;

4 . 批量处理的两种情况 :

    多条语句批量处理 : Statement (InnoDB引擎和MyIsam引擎) ;

    同一条语句批量传参 : PreparedStatement (InnoDB引擎和MyIsam引擎) ;

5 . Statement/PreparedStatement 对象 . executeBatch( ) 执行批量操作 , 之后用 . clearBatch( ) 方法清除缓存 , 如果是PreparedStatement对象的话 , 之后还需要执行 . clearParameters 方法清除参数 ; 

十一 . BLOB好TEXT类型处理

1 . BLOB是可变的数据类型 , 一般的 , 开发中是不会把二进制的文件 , 如图片 , 音频 , 视频存放在数据库中的 , 一般的把文件存储的路径持久化在数据库中 , 如果以后需要获取 , 那么只需要从某个路径去找即可 ;

2 . MySQL中的TEXT类型 , 和VARCHAR是一样的 , 就仅仅是容量不一样而已 , 一般用于存储文本 , 在Java代码中 , 代码是相同的 , 都是作为String类型处理 ;

数值类型  取值范围
binary(M)  字节数为M , 允许长度为0~M的定长二进制字符串
varbinary(M)  允许长度为0~M的变长二进制字符串 , 字节数为值得长度+1
bit(M)  M位二进制数据 , M最大值为64
tinyblob  可变长二进制数据 , 最多255个字节
blob  可变长二进制数据 , 最多2的16次方-1个字节(65535)
mediumblob  可变长二进制数据 , 最多2的24次方-1个字节(16M)
longblob  可变长二进制数据 , 最多2的32次方-1个字节(4G)
字符类型  允许的长度  存储空间
char(M)  M字节  M为0~255之间的整数
varchar(M)  M字节  M为0~65535之间的整数 
tinytext  0~255字节  值得长度+2个字节
text  0~65535字节  值得长度+2个字节
mediumtext  0~167772150字节  值额长度+3个字节
longtext  0~4294967295字节  值得长度+4个字节

十二 . 数据库连接池

1 . 数据库资源(Connection)是一种关键的 , 有限的 , 珍贵的资源 ;

2 . 普通的JDBC数据库连接使用DriverManager来获取 , 每次向数据库建立连接的时候都要讲Connection加载到内存中 , 再验证用户名和密码 , 需要数据库连接的时候就向数据库要求一个 , 执行完成之后再断开 , 这样的方式将会消耗大量的资源和时间 ;

3 . 数据库的连接资源并没有得到很好的重复利用 , 若同时有几百人甚至几千人在线 , 频繁的进行数据库连接操作将会占用很多的系统资源 , 严重的甚至导致服务器的崩溃 ;

4 . 对于每一次数据库连接 , 使用完后都得断开 , 否则 , 如果程序出现异常未能关闭 , 将会导致数据库系统中的内存泄漏 , 最终将导致重启数据库 ;

5 . 这种开发不能控制被创建的连接对象数 , 系统资源会被毫无顾忌的分配出去 , 如连接过多 , 也可能导致内存泄漏 , 服务器崩溃 ;

6 . 连接池具有的属性

     ⑴ . 连接数据库四要素 : driverClassName , url , userName , password ;

     ⑵ . 初始连接数(连接池中初始存在的连接对象) ;

     ⑶ . 最大连接数(连接池中最多存在的连接对象) ;

     ⑷ . 最小连接数(连接池中最少存在的链接对象) ;

     ⑸ . 最大空闲时间(获取连接对象后却没有连接数据库的时间 , 达到该时间后连接对象会释放 , 重新还给连接池) ;

     ⑹ . 最大等待时间(在规定时间内尝试去获取连接) ;

7 . 连接池思想其本质就是缓存思想 , 在java中 , 连接池使用javax.sql.DataSource接口来导入 , 和JDBC一样 , 由第三方组织提供实现 ;

8 . 常用的DataSource的实现

     ⑴ . druid : 阿里巴巴提供的连接池(德鲁伊) , 号称是世界上最好的连接池 , 它的功能也不仅仅是连接池 ;

     ⑵ . DBCP : 由Apache公司提供的开源连接池 , Spring框架推荐 ;

     ⑶ . C3P0 : Hibernate推荐的 , 在2007年之后就没有更新了 , 性能比较差 ; 

9 . DataSource(数据源)和连接池(Connection Pool)是同一个概念 , 类似于java中说的对象和实例 , 此处不必纠结 ;

10 . 使用连接池和不适用连接池的显著区别在哪里 ?

      ⑴ . 获取连接 : 不适用连接池的时候使用DriverManager获取 ; 

                            使用连接池的时候通过DataSource对象 . getConnection方法来得到一个连接 ;

      ⑵ . 释放连接 : 都是使用con.close()方法来释放连接 , 但前者会直接断开和数据库的连接 ;

                             后者会将连接还给连接池 , 其他Connection对象还可以再次使用该连接; 

猜你喜欢

转载自blog.csdn.net/dyz4001/article/details/80290831