1. JDBC的简介
概述: 就是Java用来操作不同数据库(DBMS)的类库(技术), 本质就是一些类和接口.
/*
类: DriverManager
接口: Driver, Connection, Statement, PreparedStatement, ResultSet
*/
//Java Data Base Connectivity, Java数据库连接(技术).
/*
集合: 就是Java用来存储不同类型数据的容器, 本质就是一些类和接口.
接口: Collection, Set, List, Map
类: ArrayList, HashSet, HashMap
面试题: 请求写代码实现, 模拟栈的数据结构(先进后出)特点?
IO流: 就是Java用来传输数据的技术, 本质就是一些类和接口.
抽象类: InputStream, OutputStream, Reader, Writer
实现类: FileInputStream, BufferedInputStream, FileReader, BufferedReader
总结: 集合的顶层都是接口, IO流的顶层都是抽象类.
*/
核心功能:
A: 连接数据库.
B: 向数据库发送SQL语句.
C: 操作数据库返回的 结果集.
如果操作的是更新语句(增删改), 返回的结果集是: int 类型
如果操作的是查询语句, 返回的结果集是: ResultSet 类型
- 什么是驱动?
就是设备间进行通信的桥梁.
- JDBC的原理是什么:
我们知道JDBC是用来操作不同数据库的, 但是操作不同的数据库需要使用不同的驱动.
eg: 我们想操作MySQL数据库, 就需要安装MySQL的驱动, 我们想操作Oracle数据库, 就需要安装Oracle数据库的驱动, 如果我们操作SQLServer数据库,就需要安装SQLServer数据库的驱动, 这样做是比较麻烦的. 因为Java已经提供了大量的类和接口了, 但是要要求额外记忆一些其他的类和接口, 这样就增加了程序员的学习难度. 后来Sun公司发现了这个问题, 就和各大数据库生产商协商决定, 由Sun公司提供统一的规范(就是一些类和接口), 数据库生产商提供具体的实现. Sun公司提供的这些类和接口就是: JDBC.
4. JDBC的代码演示
A: 创建一个数据库web04.
B: 在数据库web04中创建一个表(users);
create table users(
id int primary key auto_increment;
username varchar(20),
password varchar(20)
);
C: 往数据表中添加数据.
insert into user values(null,'aaa','123');
insert into user values(null,'bbb','321');
insert into user values(null,'ccc','456');
insert into user values(null,'ddd','654');
D: 通过JDBC操作表数据.
1) 导入驱动.
2) 注册驱动.
3) 获取连接对象.
4) 根据连接对象, 获取可以操作SQL语句的对象.
5) 执行SQL语句, 获取结果集.
如果操作的是更新语句(增删改), 返回的结果集是: int 类型
如果操作的是查询语句, 返回的结果集是: ResultSet 类型
6) 操作结果集.
7) 释放资源.
5. JDBC的API详解之: DriverManager(类)
作用: 主要用于驱动管理及获取连接对象的.
作用一: 注册驱动.
// MySQL的驱动或者Oracle的驱动
public static void registerDriver(Driver driver); //注册驱动的意思, 形参是谁的驱动, 就注册谁.
//Driver类就是MySQL数据库提供的 驱动类
public class com.mysql.jdbc.Driver implements java.sql.Driver{
}
//记忆: 实际开发中, 我们不用上述的方式注册驱动, 因为上述注册驱动的方式会导致驱动程序注册两次.
//所以: 我们通过反射的方式加载 com.mysql.jdbc.Driver类的字节码文件, 从而来自动 注册驱动.
Class.forName("com.mysql.jdbc.Driver"); //驱动类的全路径
作用二: 获取连接对象.
public static Connection getConnection(String url, String username, String password); //获取连接对象.
/*
url: 数据库连接字符串.
格式:
大白话: 连接方式:要操作的DBMS://要操作的数据库的IP地址或者主机名:端口号/要操作的具体的数据库
专业: 协议:子协议:要操作的DBMS://要操作的数据库的IP地址或者主机名:端口号/要操作的具体的数据库
例如:
jdbc:mysql://127.0.0.1:3306/web04
jdbc:mysql://localhost:3306/web04
如果操作的是本地数据库(DBMS), 上述的写法可以优化为:
jdbc:mysql:///web04
username: 要操作的数据库(DBMS)的账号
password: 要操作的数据库(DBMS)的密码
*/
6. JDBC的API详解之: Connection(接口)
Connection: 连接对象
作用一: 获取可以执行SQL语句的对象. //掌握
public Statement createStatement(); //获取可以执行SQL语句的对象.
public PreparedStatement prepareStatement(String sql); //获取可以执行SQL语句的对象, 具有预编译功能, 可以解决SQL注入攻击问题.
作用二: 可以进行事务管理.
public void setAutoCommit(boolean flag); //设置是否开启事务的自动提交功能, 相当于我们昨天讲解的: 开启事务.
public void commit(); //提交事务
public void rollback(); //事务回滚
public void setTransactionIsolation(int level); //设置事务的隔离级别
Connection接口中的常量:
public static final int TRANSACTION_NONE = 0;
public static final int TRANSACTION_READ_UNCOMMITTED = 1;
public static final int TRANSACTION_READ_COMMITTED = 2;
public static final int TRANSACTION_REPEATABLE_READ = 4;
public static final int TRANSACTION_SERIALIZABLE = 8;
7. JDBC的API详解之: Statement(接口)
Statement: 可以操作SQL语句的对象.
作用一: 执行SQL语句. //掌握
public ResultSet executeQuery(String sql); //执行查询语句
public int executeUpdate(String sql); //执行更新语句
作用二: 可以执行批处理.
//批处理只针对更新语句有效.
public void addBatch(String sql); //把SQL语句添加到批处理(指令)中.
public int[] executeBatch(); //执行批处理(指令)
public void clearBatch(); //清除批出(指令)
users: 添加5条数据
orders: 删除2条数据, 修改4条数据
orderitem: 添加10条数据, 改3条数据
exam: 删5条数据
8. JDBC的API详解之: ResultSet(接口)
ResultSet: 执行查询语句后的结果集对象.
public boolean next(); //判断结果集中是否还有数据. 类似于Iterator#hasNext().
public XXX getXxx(int columnIndex); //根据列的编号, 获取该列的信息, Xxx是数据类型的意思
public XXX getXxx(String columnName); //根据列的名字, 获取该列的信息, Xxx是数据类型的意思, 个人建议用这种方式.
//getInt(), getString(), getObject();
9. JDBC释放资源的优化代码. //重点掌握.
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
//2 alter + enter: 处理异常
Class.forName("com.mysql.jdbc.Driver");
//3
conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
//4
stat = conn.createStatement();
//5
String sql = "select * from users";
rs = stat.executeQuery(sql);
//6
while (rs.next()) {
int uid = rs.getInt("uid");
String username = rs.getString("username");
String password = rs.getString("password");
System.out.println(uid + "..." + username + "..." + password);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//7
try {
if(rs != null) {
rs.close(); //alt + ↑, 代码的向上移动
rs = null; //GC会优先回收null对象.
// System.out.println(1/0);
System.out.println("rs 关了");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (stat != null) {
stat.close();
stat = null;
System.out.println("stat 关了");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
conn = null;
System.out.println("conn 关了");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
10. JDBC对表数据的CURD操作
public class Test02_JDBC对数据的CURD操作 {
//alter + enter: 给出建议 Junit4
/**
* JDBC的查
*/
@Test
public void method1() {
System.out.println("JDBC的查, 自己实现");
}
/**
* JDBC的增
*/
@Test
public void method2() {
Connection conn = null;
Statement stat = null;
try {
//2 alter + enter: 处理异常
Class.forName("com.mysql.jdbc.Driver");
//3
conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
//4
stat = conn.createStatement();
//5
String sql = "insert Into users values(null,'tianqi','pw567')";
int num = stat.executeUpdate(sql);
//6
if(num > 0) {
System.out.println("添加成功");
} else {
System.out.println("添加失败");
}
//7
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* JDBC的改
*/
@Test
public void method3() {
Connection conn = null;
Statement stat = null;
try {
//2 alter + enter: 处理异常
Class.forName("com.mysql.jdbc.Driver");
//3
conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
//4
stat = conn.createStatement();
//5
String sql = "update users set password='777' where uid = 6;";
int num = stat.executeUpdate(sql);
//6
if(num > 0) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
//7
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* JDBC的删
*/
@Test
public void method4() {
Connection conn = null;
Statement stat = null;
try {
//2 alter + enter: 处理异常
Class.forName("com.mysql.jdbc.Driver");
//3
conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
//4
stat = conn.createStatement();
//5
String sql = "delete from users where uid = 6;";
int num = stat.executeUpdate(sql);
//6
if(num > 0) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
//7
stat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
11. JDBCUtils工具类的抽取
方式一: 普通抽取
public class JDBCUtils {
//1. 构造私有.
//2. 注册驱动, 静态代码块实现.
//3. 获取连接对象.
//4. 释放资源. try-catch-finally 语句的嵌套实现.
}
此时, 虽然我们已经成功的抽取出来了JDBCUtils工具类, 但是和一个开发原则相违背"对修改关闭, 对扩展开放".
例如: 如果我们想操作web05这个数据库了, 就得修改工具类中url的写法, 如果我们操作的数据库的用户名和密码
改变了, 我们也得修改工具类中username,password的写法, 这样做扩展性较差.
于是, 我们就想着如何解决这个问题?
能不能创建一个文件(配置文件), 里边记录的是各项配置信息, 然后由工具类读取该配置文件的信息即可.
这个配置文件就是: **.properties
Properties集合类:
概述: 它是一个双列集合, 键值都是String类型, 它是Hashtable集合的子类.
//Properties集合是唯一可以直接和IO流相结合使用的集合类.
//它可以直接从流中读取数据, 也可以直接写数据到流中.
成员方法:
public void load(InputStream is); //从流中读取数据
public void load(Reader r); //从流中读取数据
public void store(OutputStream os); //写数据到流中
public void store(Writer w); //写数据到流中
public String getProperty(String key); //根据键获取值
public void setProperty(String key,String value); //设置键值对
面试题:
Hashtable和HashMap的区别?
HashMap: 线程不安全, 效率高, 可以存null值和null键.
JDK1.2出来来.
Hashtable: 线程安全, 效率低. 不可以存null值和null键.
JDK1.0出来的.
整个Java命名规范是从: JDK1.2开始完善的.
方式二: 结合配置文件的使用
public class JDBCUtils {
//1. 构造私有.
//2. 定义变量, 记录配置文件的信息.
//3. 读取配置文件, 并将读取到的值赋值给变量.
//4. 注册驱动, 静态代码块实现.
//5. 获取连接对象.
//6. 释放资源. try-catch-finally 语句的嵌套实现.
}
12. SQL注入攻击问题
概述:
代码演示SQL注入攻击问题:
解决方案: PreparedStatement接口的预编译, 占位符.
今日总结:
1. JDBC的原生态代码.
2. JDBC的优化释放资源的代码
3. Properties的使用
4. 抽取JDBCUtils工具类
5. 解决SQL注入攻击问题
网友评论