一 . 什么是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对象还可以再次使用该连接;