文章目录
JDBC总结
一、JDBC简介
- JDBC(Java Data Base Connectivity)是Java语言访问数据库的一套API应用程序编程接口。
- 本质上来说就是调用者(程序员)和实现者(数据库厂商)之间的协议。
- jDBC的实现由数据库厂商以驱动程序的形式提供。
- JDBC API可以让开发人员使用纯java的方式来链接数据库,并进行操作。
二、JDBC原理
三、JDBC对象介绍
Jdbc常见类
JDBC中的核心类有:DriverManager,Connnection,Statement和ResultSet
1、DriverManager(驱动管理器)的作用有两个
-
注册驱动:这可以让JDBC知道要使用的是哪个驱动
DriverManager.registerDriver()方法:
了解即可,注册驱动一般用Class.forName()
-
获取Connection:如果可以获取到Connection,那么说明已经与数据库连接上了
getConnection()方法:
2、Connection对象表示连接,与数据库的通讯都是通过这个对象展开的:
- Connection最为重要的一个方法就是用来获取Statement对象
Statement statement = connection.createStatement();
代码:
3、Statement是用来向数据库发送SQL语句的,这样数据库就会执行发送过来的SQL语句:
常用的Statement方法
int executeUpdate(String sql):执行更新操作(insert,update,delete等)
- 执行更新操作,即insert,update,delete语句
- 也可以执行create table,alter table,drop table等语句,但很少用
- 返回值为操作行数
ResultSet executeQuery(String sql):执行查询操作,数据库在执行查询后会把查询结果ResultSet返回
- 执行查询操作,即select语句
- 返回ResultSet,即结果集
boolean execute();
- 可以用来执行executeUpdate和executeQuery两个方法能执行的所有sql语句,即可以执行增删改查所有sql语句
- 该方法的返回的是一个boolean类型,表示SQL语句是否有结果集
- 如果用该方法执行更新语句,那么还要调用int
getUpdateCount()来获取insert,update,delete语句所影响的行数 - 如果使用该方法执行查询语句,那么还要调用ResultSet getResult()来获取select语句的查询结果
三种Statement对象
Statement 对象
- 作用:用于执行不带参数简单 SQL 语句
- 特点:每次执行 SQL 语句,数据库都要执行 SQL 语句的编译,最好用于仅执行一次查询并返回结果的情形,
- 效率高于 PreparedStatement
PreparedStatement
- 作用:用于执行带 或 不带 IN参数 的预编译 SQL 语句
- 特点:
- ① 是预编译的, 在执行可变参数的一条 SQL 语句时,比 Statement 的效率高,因为 DBMS 预编译一条 SQL,当然会比多次编译一条 SQL 的效率要高
- ② 安全性好,有效防止 SQL 注入等问题
- ③ 对于多次重复执行的语句,效率会更高一点,并且这种情况下也比较适合使用 batch
- ④ 代码的可读性和可维护性好
CallableStatement
- 作用:用于执行对数据库存储过程 的调用
- 特点:提供了对输出和输入参数的支持
- 此接口具有对 PreparedStatment 接口提供的输入输出参数的支持
代码:
4、ResultSet对象表示查询结果集,只有在执行查询操作后才会有结果集的产生
- 结果集是一个二维的表格,有行有列。
- 操作结果集要利用ResultSet内部的“行光标”,以及获取当前行上的每一列上的数据
boolean next();是行光标移动到下一行,并返回移动后的行是否存在
getXXX(int index);获取指针所指向的当前行数据
colose();释放资源
四、JDBC编程步骤
需要引入mysql-connector-java-5.1.39-bin.jar工具包。
1、加载mysql数据库驱动
/**
* 所有的java.sql.Driver实现类,都提供了static块,
* 块内的代码就是把自己注册到DriverManager中
*/
Class.forName("com.mysql.jdbc.Driver"); //加载驱动类(注册驱动)
/*等价于*/
com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver(); //注册驱动
DriverManager.registerDriver(driver);
一般都用Class.forName()方法加载驱动。
2、获取链接
//设置参数
String url = "jdbc:mysql://localhost:3306/mybase";
String username = "root";
String password = "123";
//使用url,username,password,得到连接对象
Connection connection = DriverManager.getConnection(url,username,password);
3、获取Statement
(1)获取Statement对象
Statement stm = conn.createStatement();
(2)获取preparedStatement对象
String sql = "select * from emp where job=?";
pstm = conn.prepareStatement(sql); //创建sql半成品
pstm.setString(1,"clerk"); //参数绑定
①创建sql半成品:通过连接获得PreparedStatement对象,创建时将SQL语句中取值发生变化的部分用占位符?代替。
②参数绑定,即为?赋值(set[type](1,2)方法
)第一个参数代表?位置,从1开始;第二个参数是具体取值。
4、执行SQL语句
(1)如果是Statement对象的查询,使用ResultSet rs = stm.executeQuery(sql);
(2)如果是preparedStatement对象的查询,使用ResultSet rs = pstm.executeQuery();
(3)如果有很多sql语句需要执行,就要使用批处理。
5、处理结果集(查询需要)
while(rs.next()){
String number = rs.getString(1); //通过列编号来获取该列的值
String name = rs.getString("name"); //通过列名称来获取该列的值
int age = rs.getInt(3);
String gender = rs.getString(4);
System.out.println(number + "," + name + "," + age + "," + gender);
}
6、关闭链接
// 倒关(先得到的资源后关闭,后得到的资源先关闭)
rs.close();
stm.close();
conn.close(); //这个必须要关
五、规范代码示例
1、创建Statement连接数据库
import java.sql.*;
public class testStatement {
public static void main(String[] args) {
Connection conn = null;
Statement stm = null;
ResultSet rs = null;
try {
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
String url = "jdbc:mysql://localhost:3306/mybase?serverTimezone=UTC";
String user = "root";
String password = "159357";
conn = DriverManager.getConnection(url, user, password);
//3、创建Statement对象
stm = conn.createStatement();
//4、执行sql语句
//查询数据库statement.executeQuery(查询sql)
String sql = "select * from emp";
rs = stm.executeQuery(sql);
//修改操作数据库 statement.executeUpdate(增删改sql)
/*String sql = "insert into emp(ename,job,deptno) values('小龙人','manager',10)";
String sql = "delete from emp where ename='小龙人'";
String sql = "update emp set job='leader' where ename='张伟'";
int lines = stm.executeUpdate(sql);
System.out.println("影响的行数"+lines);
*/
//5、处理结果集
while(rs.next()){
//int empno = rs.getInt(1);
int empno = rs.getInt("empno");
String ename = rs.getString(2);
String job = rs.getString(3);
int mgr = rs.getInt(4);
Date hiredate = rs.getDate(5);
double sal= rs.getDouble(6);
//double comm = rs.getDouble(7);
double comm = rs.getDouble("comm");
int deptno = rs.getInt(8);
System.out.println(empno+" "+ename+" "+job+" "+mgr
+" "+hiredate+" "+sal+" "+comm+" "+deptno);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//6.关闭链接
if(resultSet != null)
{
resultSet.close();
}
if(statement != null)
{
statement.close();
}
if(connection != null)
{
connection.close();
}
}
}
3、创建preparedStatement连接数据库
pstm构建动态sql
解决Sql注入攻击漏洞,可以使用PreparedStatement来执行sql。它是
Statemnet的一个子接口使用步骤分为3步:
(1)创建:通过链接获得PreparedStatement对象
String sql="select * from user_luxw where username=? Andpassowrd=?";
PreoparedStatment pstm = conn.prepareStatement(sql);
创建时,将SQL语句中取值发生变化的部分用占位符(?)替代。
(2)给?赋值(也称参数绑定)
/*使用set[Type]方法给?赋值。其中Type表示?表示?位置的数据类型。第一个参数代表问号
位置从1开始;第二个参数是具体取值,比如:*/
pstm.setString(1,username);
pstm.setString(2,password);
(3)执行SQL
pstm.executeQuery();
pstm.executeUpdate(); //执行更新时使用
此时JDBC将所有?对应的参数发送至数据库服务器,调用在共享池中由第一步创建的预编译的SQL并执行
完整代码:
package jdbc;
import java.sql.*;
import java.util.Date;
/**
- 类说明:
- JDBC创建PreparedStatement对象连接数据库
*/
public class testPreparedStatement {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接
String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "123";
conn = DriverManager.getConnection(url, user, password);
// 3.创建PreparedStatement,预编译sql语句
String sql = "select * from emp where job=?";
pstm = conn.prepareStatement(sql);//创建sql半成品
pstm.setString(1,"clerk");//参数绑定
//4.执行sql语句
rs = pstm.executeQuery();
//5.处理结果集
while(rs.next()){
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
String job = rs.getString(3);
int mgr = rs.getInt("mgr");
Date hiredate = rs.getDate(5);
double sal = rs.getDouble("sal");
double comm = rs.getDouble("commit");
int deptno = rs.getInt(8);
System.out.println(empno+" "+ename+" "+job+" "+mgr+" "+hiredate+" "+sal+" "+comm+" "+deptno);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.关闭连接/释放资源
try {
rs.close();
pstm.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
4、Statement和preparedStatement比较
- statement的执行过程: 创建stm对象—>进行编译—>执行(执行一条sql语句10秒).
- PreparedStatement的执行过程:
创建pstm对象(sql半成品)—>设置值—>执行发送数据(执行一条sql语句需要12秒,但是设置sql和值只需要2秒)
5、批处理
(1)Statement完成批处理
- 使用Statement对象添加要批量执行SQL语句
- 执行批处理SQL语句:
Statement.executeBatch();
- 清除批处理命令:
Statement.clearbatch();
优点:可以向数据库发送多条不同的SQL语句。
缺点:SQL语句没有预编译。
当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。
完整代码:
import java.sql.*;
/*
* statement批处理
*/
public class testStatementBatch {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//加载链接
Class.forName("com.mysql.jdbc.Driver");
//获取链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybase?serverTimezone=UTC", "root", "159357");
//创建Statement
Statement stm = conn.createStatement();
String sql = "insert into emp(ename,job,deptno) values('小龙人','clerk',20)";
String sql1 = "insert into emp(ename,job,deptno) values('美人鱼','leader',10)";
String sql2 = "update emp set ename='小龙人1' where ename='小龙人'";
//添加批处理
stm.addBatch(sql);
stm.addBatch(sql1);
stm.addBatch(sql2);
//执行批处理ִ
stm.executeBatch();
//清除批处理
stm.clearBatch();
//释放资源
stm.close();
conn.close();
}
}
(2)PreoparedStatment批处理
- 采用
PrepareStatement.addBatch()
实现批处理
优点:发送的是预编译后的SQL语句,执行效率高
缺点:只能应用在SQL语句相同,但参数不同的批处理中,因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。
import java.sql.*;
/*
* prepareStatement批处理
*/
public class testPreparedStatemnetBatch {
public static void main(String[] args) throws Exception {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获取链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybase?serverTimezone=UTC", "root", "159357");
String sql="insert into emp(empno,ename,deptno) values(?,?,?)";
//创建preparedStatemet
PreparedStatement pstm = conn.prepareStatement(sql);
//pstm绑定数据
for(int i=3008;i<4008;i++){
pstm.setInt(1, i);
pstm.setString(2, "李白"+i);
pstm.setInt(3,20);
//添加批处理
pstm.addBatch();
//ִ执行批处理
if(i%100==0){
pstm.executeBatch();
pstm.clearBatch();
}
}
//执行批处理
pstm.executeBatch();
//释放资源
pstm.close();
conn.close();
}
}