DriverManager类—>Connection类—>Statement类/PreparedStatement类
由DriverManager(驱动管理对象)得到 Connection(数据库连接对象)
由Connection(数据库连接对象)得到 Statement和PreparedStatement(执行sql的对象)
由Statement/PreparedStatement(执行sql的对象)去执行SQL语句
DriverManager:驱动管理对象
注册驱动:告诉程序该使用哪一个数据库驱动jar
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
方法:
static void registerDriver(Driver driver);
等同于:
Class.forName("com.mysql.cj.jdbc.Driver");
获取数据库连接:
方法:
static Connection getConnection(String url, String user, String password)
url:指定连接的路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
例子:jdbc:mysql://localhost:3306/db3
细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
user:用户名
password:密码
Connection:数据库连接对象
获取执行sql 的对象
Statement createStatement()
PreparedStatement prepareStatement(String sql)
管理事务:
开启事务 :setAutoCommit(boolean autoCommit) :调用该方法 设置参数为false,即开启事务
提交事务:commit()
回滚事务:rollback()
Statement/PreparedStatement:执行sql的对象
Statement对象
①boolean execute(String sql) 可以执行任意的sql
返回值:返回一个boolean值,表明执行该SQL语句是否返回了ResultSet。(由于执行SQL语句比较麻烦,使用较少,但是在不知道SQL语句类型是,可以使用它。)
package cn.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo02 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、导入jar包
//2、注册驱动(可省略)
Class.forName("com.mysql.cj.jdbc.Driver");
//3、获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/duobiaochaxun ? serverTimezone=UTC&characterEncoding=utf-8&useSSL=false", "root", "123abc");
//4、定义SQL语句
String sql1 = "insert into account values (null,'lw',3000)";
String sql2 = "update account set balance = 4000 where NAME = 'lisi'";
//5、获取执行SQL对象
Statement stmt = conn.createStatement();
//6、执行SQL
//返回的是一个boolean值,表明执行该SQL语句是否返回了ResultSet。
boolean execute1 = stmt.execute(sql1);
boolean execute2 = stmt.execute(sql2);
//7、处理结果
System.out.println(execute1);
System.out.println(execute2);
//8、释放资源
stmt.close();
conn.close();
}
}
(出现异常,在这里我将其抛出,但是在实际开发过程中最好将异常处理。)
②int executeUpdate(String sql)执行DML(insert、update、delete) 语句、DDL(create,alter、drop)语句.
返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功(返回值>0的则执行成功,反之,则失败)
package cn.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo03 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
//1、导入jar包
//2、注册驱动(可省略)
Class.forName("com.mysql.cj.jdbc.Driver");
//3、获取数据库连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/duobiaochaxun ? serverTimezone=UTC&characterEncoding=utf-8&useSSL=false", "root", "1234qwe");
//4、定义SQL语句
String sql = "update account set balance = 4500 where balance = 400";
//5、获取执行SQL对象
stmt = conn.createStatement();
//6、执行SQL
//返回的是SQL语句执行影响的行数
int i = stmt.executeUpdate(sql);
//7、处理结果
if (i>0){
System.out.println("更新成功");
System.out.println(i);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//8、释放资源
//可能还没有执行到stmt = conn.createStatement();就会报错,那么释放时就会有空指针异常
//那么就是当stmt不为空时,我们才需要去释放。等于null就不需要释放
if (stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//conn释放的时候也是一样的道理,可能还没有赋值就已经出现异常,那么就没有必要释放。
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
(出现异常,要利用try…catch…finally处理)
③ResultSet executeQuery(String sql) 执行DQL(select)语句
ResultSet:结果集对象,封装查询结果
- boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
getXxx(参数):获取数据
Xxx:代表数据类型 如: int getInt() , String getString()
参数:- 1.int:代表列的编号,从1开始 如: getString(1)
- 2.String:代表列名称。 如: getDouble(“balance”)
package cn.jdbc;
import java.sql.*;
public class Demo04 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1.导入jar包
//2.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//3.获取数据库连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/duobiaochaxun ? serverTimezone=UTC&characterEncoding=utf-8&useSSL=false", "root", "123321");
//4.定义SQL语句
String sql = "select * from account";
//5.获取SQL执行对象
stmt = conn.createStatement();
//6.执行SQL
rs = stmt.executeQuery(sql);
//7.处理结果
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString("NAME");
int balance = rs.getInt(3);
System.out.println("id:" + id + " name: "+ name +" balance:"+balance);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//8.释放资源
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
PreparedStatement对象
PreparedStatement:执行sql的对象
SQL注入问题:
在SQL语句中参数不确定的情况下我们可以拼接SQL语句,但是这样在某些情况下会造成条件恒等,造成安全性问题。
例:String sql = “select * from user where username = '”+username+"’ and password = ‘"+password+"’ ";
如果密码输入 a’ or ‘1’ = ‘1.那么SQL语句就会变成 "select * from user where username = ‘???’’ and password = a’ or ‘1’ = '1 ';那么不论用户名是多少,这条语句执行结果总是对的。
解决SQL注入问题:
我们使用PreparedStatement对象来解决,对于未确定的参数利用?作为占位符。
PreparedStatement使用注意:
①在定义SQL语句时,要给未确定的参数以?来占位。
②在获取PreparedStatement对象时就要传入SQL语句。
③在调用PreparedStatement的方法执行SQL之前要给占位符的参数赋上真正的值
④PreparedStatement继承自Statement,因此Statement中的方法PreparedStatement中均有。
int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)
ResultSet executeQuery() : 执行预编译的查询sql语句(DQL)
④利用PreparedStatement的方法执行SQL语句时不用再传入参数。
package cn.jdbc;
import java.sql.*;
public class preparedstatement {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Connection conn = null;
PreparedStatement pstmt = null;
try {
//1、导入jar包
//2、注册驱动(可省略)
Class.forName("com.mysql.cj.jdbc.Driver");
//3、获取数据库连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/duobiaochaxun ? serverTimezone=UTC&characterEncoding=utf-8&useSSL=false", "root", "123321");
//4、定义SQL语句
String sql = "update account set balance = 10 where NAME = ? and balance = ? ";
//5、获取执行SQL对象(预编译SQL)
pstmt = conn.prepareStatement(sql);
//6、给?赋值
pstmt.setString(1,"wdh");
pstmt.setInt(2,123);
//7、执行SQL
int i = pstmt.executeUpdate();
//7、处理结果
if (i>0){
System.out.println("更新成功");
System.out.println(i);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//释放资源
if (pstmt != null){
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
PreparedStatement对象和 Statement对象对比可参考下面博客:
https://www.cnblogs.com/simpleyou/p/11632366.html