文章目录
- JDBC简介
- 概念
- 本质
- 好处
- JDBC快速入门
- JDBC中API详解
- DriverManager
- 驱动管理类作用
- 注册驱动
- 获取连接
- Connection
- 数据库连接对象作用
- 获取执行SQL的对象
- 事务管理
- Statement
- 作用
- 执行SQL语句
- ResultSet
- 原理
- 使用步骤
- PreparedStatement
- SQL注入
- 获取对象
- 操作步骤
- 原理
- 好处
- JDBC工具类
- 三层开发业务的案例分析
- 图解
- 三层结构模型
- 分层的好处
- 数据库连接池
- 简介
- 实现
- Druid连接池
- 常用的配置参数
- 基本使用
- 使用步骤
JDBC简介
概念
就是使用Java语言操作关系型数据库的一套API
全称:Java DataBase Connectivity Java数据库连接
本质
是一套操作所有关系型数据库的规则,即接口
好处
- 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
- 可随时替换底层数据库,访问数据库的Java代码基本不变
JDBC快速入门
操作步骤
1. 创建工程,导入驱动jar包
在当前模块下创建lib文件夹,将jar包放到lib文件夹下,
2. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
3. 获取连接
Connection conn = DriverManager.getConnection(url,user,password);
4. 定义SQL语句
String sql = "select ...";
5. 获取执行SQL对象
Statement stmt = conn.createStatement();
6. 执行SQL
boolean result = stmt.executeQuery(sql);
7. 处理返回结果
System.out.println(result);
8. 释放资源
stmt.close();
conn.close();
JDBC中API详解
DriverManager
驱动管理类作用
- 注册驱动
- 获取数据库连接
注册驱动
Class.forName(“com.mysql.jdbc.Driver”);
Driver类源码
此处也可写成DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 用前面代码创建Driver类,创建时静态代码块又会创建Driver类,使其创建了俩次,所有用最上面class那个代码
获取连接
static Connection getConnection(String url,String user,String password)
- url:连接路径
- user:用户名
- password:密码
连接路径详解
Connection
数据库连接对象作用
- 获取执行SQL的对象
- 管理事务
获取执行SQL的对象
- 普通执行SQL对象
Statement createStatement()
- 预编译SQL的执行SQL对象:防止SQL注入
PrepareStatement prepareStatement(sql)
事务管理
开启事务:SetAutoCommit(boolean autoCommit):
true为自动提交事务,false为手动提交事务(开启事务)
提交事务:commit()
回滚事务:rollback()
Statement
作用
执行SQL语句
执行SQL语句
- int executeUpdate(sql):执行DML,DDL语句
- 返回值:DDL执行成功返回0
- DML语句影响的行数
- ResultSet executeQuery(sql):执行DQL语句
- 返回值:ResultSet结果集对象
- 返回值:ResultSet结果集对象
ResultSet
原理
- ResultSet内部有一个指针,刚开始记录开始位置
- 调用next方法,ResultSet内部指针会移动到下一行数据,存在返回true,不存在返回false
- 我们可以通过ResultSet得到一行数据getXxx得到某列数据
使用步骤
- 游标向下移动一行,并判断改行是否有数据:next()
- 获取数据:getXxx(参数)
while(rs.next()){
re.getXxx(参数);
}
PreparedStatement
SQL注入
用户在页面提交数据的时候人为的添加一些特殊字符,使得sql语句的结构发生了变化,最终可以在没有用户名或者密码的情况下进行登录
获取对象
PreparedStatement是Statement的子接口,可以防止sql注入问题
PreparedStatement prepareStatement(String sql)
注意:sql提前创造好的,sql语句中需要参数,使用?占位
select * from user where username = ?and password = ?;
操作步骤
1.PreparedStatement pstmt = conn.prepareStatement(sql);
2.pstmt.setXxx(int index,要放入的值);
第一个参数:int index:表示sql语句中问号出现的位置,从1开始计数
第二个参数:给问号的位置传入的值
3.执行,不需要再传递sql了
pstmt.executeQuery(); 执行select
pstmt.executeUpdate(); 执行insert,update,delete
原理
- 在获取PreparedStatement对象时,将SQL语句发送给mysql服务器进行检查,编译
- 执行时就不用再进行这些步骤了,速度更快
- 如果sql模板一样,则只需进行一次检查,编译
好处
- 预编译SQL,性能更高
- 防止SQL注入:将敏感字符进行转义
JDBC工具类
通过学习上述代码,我们发现在执行增删改查的时候,除了sql语句和执行sql语句的对象不同外,其他都相同,所以我们可以将其重复的抽成一个抽象类
下面是我所写的代码:
public class JdbcUtil {
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/db1?useSSL=false";
private static final String USER = "root";
private static final String PASSWORD = "123456";
//注册驱动,仅执行一次,所以可以放到static代码块中
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASSWORD);
}
public static void getClose(Connection conn, Statement stmt) {
getClose(conn,stmt,null);
}
public static void getClose(Connection conn, Statement stmt, ResultSet rs) {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
public class Demo {
@Test
public void testUitl(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
conn.setAutoCommit(false);
String sql = "update user set password = ? where username = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"666");
pstmt.setString(2,"wangwu");
int count = pstmt.executeUpdate();
if (count > 0){
System.out.println("更改成功");
conn.commit();
}else {
conn.rollback();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
JdbcUtil.getClose(conn,pstmt,rs);
}
}
}
三层开发业务的案例分析
图解
三层结构模型
- web层:接收客户端发送的数据 -> 把接收的数据封装成对象 -> 调用service层方法(并传递对象) -> 根据service层方法执行结果,给客户反馈
- service层:处理业务逻辑(会调用dao层中的方法)
- dao层:和数据库交互(底层利用jdbc技术)
分层的好处
- 解耦:降低代码的依赖关系
- 可维护性:哪一层出现问题,直接维护哪一层
- 可扩展性:哪一层需要添加代码,直接添加即可
- 可重用性:一个方法可以被其他层重复调用
数据库连接池
简介
数据库连接池是个容器,负责分配,管理数据库连接(Connection),它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
实现
- 标准接口:DataSource
- 获取连接 Connection getConnection
- 常见的数据库连接池
- DBCP
- C3P0
- Druid
- Druid
Druid连接池
常用的配置参数
基本使用
核心类:DruidDataSourceFactory
public static DataSource createDataSource(Properties p);
创建一个properties配置文件,然后书写数据库连接参数(参考配置参数)
使用步骤
- 导入jar包
- 定义配置参数,定义参数
- 加载配置文件(创建properties对象)
- 获取数据库连接池对象(使用核心类构建连接池)
- 获取连接
- 执行sql语句
- 关闭资源,归还连接