提示:文章内容输出来源:拉勾教育Java就业急训营
文章目录
前言
进入了第二阶段 拉勾教育Java就业急训营,主要关于数据库
这里就没有具体的笔记,只记录出现 需要注意的问题
1. null
null,语法 是 is null , is not null.
2. having
having 运用在 group by 之后, 是分组后的过滤
having 后面可以写 聚合函数
where 进行分组前的过滤
where 后面不能写 聚合函数
3. 聚合函数
聚合函数的计算,null值。
count(1), 统计null 值,忽略所有列
count(*) 统计 null 值, 包括所有列
count(列名) 不统计null 值,所以一般选择非空的列:主键
4. sql语言笔记
4.1 使用union的时候 需要保持表都是相同的列,才可以合并
select * from student s natural inner join takes t
union
select s.id,s.name,s.dept_name,s.tot_cred,null,null, null,null,null
from student s where s.id not in (select id from takes)
4.2 group by分组可以用多个字段
select name, semester, sum(tot_cred),year
from student natural left join takes
group by student.id, year, semester
4.3 CASE WHEN函数
类似JAVA中的IF ELSE语句
下面当semester是Spring 就返回 1… (为什么设置返回1,2,3 只是为了排序而已)
select s.name, t.semester, t.year, s.tot_cred from student s, takes t
where s.id = t.id order by t.year,
case t.semester
when 'Spring' THEN 1
when 'Summer' THEN 2
when 'Fall' THEN 3
end;
5. Connection:数据库连接对象
功能:
- 获取执行sql 的对象
- Statement createStatement()
- PreparedStatement prepareStatement(String sql)
- 管理事务:
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 提交事务:commit()
- 回滚事务:rollback()
6. JDBC控制事务:
- 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
- 操作:
- 开启事务
- 提交事务
- 回滚事务
- 使用Connection对象来管理事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 在执行sql之前开启事务
- 提交事务:commit()
- 当所有sql都执行完提交事务
- 回滚事务:rollback()
- 在catch中回滚事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
//2.定义sql
//2.1 A - 500
String sql1 = "update account set balance = balance - ? where id = ?";
//2.2 B + 500
String sql2 = "update account set balance = balance + ? where id = ?";
//3.获取执行sql对象
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
//4. 设置参数
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
//5.执行sql
pstmt1.executeUpdate();
// 手动制造异常
int i = 3/0;
pstmt2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
//事务回滚
try {
if(conn != null) {
conn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
JDBCUtils.close(pstmt1,conn);
JDBCUtils.close(pstmt2,null);
}
}
6.1 事务的ACID属性
- 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性(Consistency) 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
- 隔离性(Isolation) 事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(Durability) 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
6.2 数据库的并发问题
对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种
并发问题:
- 脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的
内容就是临时且无效的。 - 不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段。之后, T1再次读取同一个字
段, 值就不同了。 - 幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行。之后, 如果 T1 再次读取同一个表, 就会多出几行。
数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题。
一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。
四种隔离级别:
7. statement vs PreparedStatement
使用Statement操作数据表存在弊端:
问题一:存在拼串操作,繁琐 PreparedStatement 能最大可能提高性能
问题二:存在SQL注入问题. PreparedStatement 可以防止 SQL 注入
8. 数据库连接池
- 数据库连接池的基本思想:就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
- 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
- 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
好处:
- 节约资源
- 用户访问高效
8.1 多种开源的数据库连接池
JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,
- DBCP 是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持。
- C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。hibernate官方推荐使用Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
- BoneCP 是一个开源组织提供的数据库连接池,速度快
- Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池
DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池
DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。
注意:
- 数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
- 当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但conn.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。
9. QueryRunner类
该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
10. ResultSetHandler接口及实现类
是使用ResultSetHandler接口的几个常见实现类实现数据库的增删改查,可以大大减少代码量,优化程序
- Class类记得toString, 不然只会返回地址
- BeanListHandler
List<Employee> list = qr.query(sql, new BeanListHandler<Employee>(Employee.class));
这里是封装了类(Employee)到集合中,若得到的结果里的字段不存在于该类中,则会出现“ ”空值 - 尽量单表查询,一个SQL对应一个表
总结
提示:这里对文章进行总结:
持续更新遇到的SQL 问题