- JDBC基础
- 什么是JDBC
- 入门程序
- 功能类
- 工具类
- SQL注入攻击
- 原理
- PreparedStatement的介绍
- 数据库连接池
- 原理
- 自定义连接池
- 归还连接
- JDBC框架
- 自定义JDBC框架
JDBC基础
什么是JDBC
用于执行SQL语句的java API,实现不同关系型数据库的连接
入门程序
-
导入jar包
-
注册驱动
-
获取连接
-
获取执行者对象
-
执行sql语句,并接收返回结果
-
处理结果
-
释放资源
功能类
DriverManager:驱动管理对象
注册驱动(告诉程序该使用哪一个数据库驱动)
获取数据库连接(获取到数据库的连接并返回连接对象)
Connection:数据库连接对象
获取执行者对象
管理事务
释放资源
Statement:执行sql语句的对象
执行DML语句
执行DQL语句
释放资源
ResultSet:结果集对象
判断结果集中是否还有数据
获取结果集中的数据
释放资源
工具类
工具类的抽取:
配置文件(在src下创建config.properties)
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db14
username=root
password=itheima
工具类
/*
JDBC工具类
*/
public class JDBCUtils {
//1.私有构造方法
private JDBCUtils(){};
//2.声明配置信息变量
private static String driverClass;
private static String url;
private static String username;
private static String password;
private static Connection con;
//3.静态代码块中实现加载配置文件和注册驱动
static{
try{
//通过类加载器返回配置文件的字节流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");
//创建Properties集合,加载流对象的信息
Properties prop = new Properties();
prop.load(is);
//获取信息为变量赋值
driverClass = prop.getProperty("driverClass");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
//注册驱动
Class.forName(driverClass);
} catch (Exception e) {
e.printStackTrace();
}
}
//4.获取数据库连接的方法
public static Connection getConnection() {
try {
con = DriverManager.getConnection(url,username,password);
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
//5.释放资源的方法
public static void close(Connection con, Statement stat, ResultSet rs) {
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection con, Statement stat) {
close(con,stat,null);
}
}
SQL注入攻击
原理
Statement对象在执行sql语句时,将一部分内容当做查询条件来执行了
PreparedStatement的介绍
- 预编译sql语句的执行者对象。在执行sql语句之前,将sql语句进行提前编译。明确sql语句的格式后,就不会改变了。剩余的内容都会认为是参数!参数使用?作为占位符
- 为参数赋值的方法:setXxx(参数1,参数2);
- 参数1:?的位置编号(编号从1开始)
- 参数2:?的实际参数
- 执行sql语句的方法
- 执行insert、update、delete语句:int executeUpdate();
- 执行select语句:ResultSet executeQuery();
数据库连接池
原理
自定义连接池
java.sql.DataSource接口:数据源(数据库连接池)。java官方提供的数据库连接池规范(接口)
- 获取数据库连接对象:Connection getConnection();
/*
自定义连接池类
*/
public class MyDataSource implements DataSource{
//定义集合容器,用于保存多个数据库连接对象
private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>());
//静态代码块,生成10个数据库连接保存到集合中
static {
for (int i = 0; i < 10; i++) {
Connection con = JDBCUtils.getConnection();
pool.add(con);
}
}
//返回连接池的大小
public int getSize() {
return pool.size();
}
//从池中返回一个数据库连接
@Override
public Connection getConnection() {
if(pool.size() > 0) {
//从池中获取数据库连接
return pool.remove(0);
}else {
throw new RuntimeException("连接数量已用尽");
}
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
归还连接
继承(无法解决)
- 通过打印连接对象,发现DriverManager获取的连接实现类是JDBC4Connection。
- 自定义一个类,继承JDBC4Connection这个类,重写close()方法。
/*
自定义Connection类
*/
public class MyConnection1 extends JDBC4Connection {
//声明连接对象和连接池集合对象
private Connection con;
private List<Connection> pool;
//通过构造方法给成员变量赋值
public MyConnection1(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url,Connection con,List<Connection> pool) throws SQLException {
super(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url);
this.con = con;
this.pool = pool;
}
//重写close()方法,将连接归还给池中
@Override
public void close() throws SQLException {
pool.add(con);
}
}
虽然自定义了一个子类,完成了归还连接的操作。但是DriverManager获取的还是JDBC4Connection这个对象,并不是我们的子类对象。而我们又不能整体去修改驱动包中类的功能!
适配器设计模式
- 有很多个需要实现的方法的时候,就可以使用适配器设计模式。提供一个适配器类,实现Connection接口,将所有功能进行实现(除了close方法)。自定义连接类只需要继承这个适配器类,重写需要改进的close()方法即可!
动态代理
- 经过适配器模式的改进,自定义连接类中的方法已经很简洁了。剩余所有的方法已经抽取到了适配器类中。但是适配器这个类还是自己编写的,也比较麻烦!所以使用动态代理的方式来改进。
JDBC框架
- 抽取出一个JDBC模板类,来封装一些方法(update、query),专门帮我们执行增删改查的sql语句!
- 将之前那些重复的操作,都抽取到模板类中的方法里。就能大大简化我们的使用步骤!
自定义JDBC框架
数据库的源信息
DataBaseMetaData(了解):数据库的源信息
ResultSetMetaData:结果集的源信息