JDBC
1.基本概念
什么是JDBC?
Java DataBase Connectivity Java 数据库连接, Java语言操作数据库(如果面试这样回答的话大概只得60分)
要想完整讲述应该是要把JDBC的本质以要说出来;那么JDBC的本事本质是什么呢?
其本质就是官方定义的一套操作所有关系型数据库的规则;
也就是接口各个数据库厂商去实现这套接口从而要提供数据库驱动jar包
;
我们可以使用这套接口进行编程,真正执行的代码是驱动jar包中的实现类
2.快速入门
快速入门就是如何建立JDBC连接;从而实现对数据库的操作
- 导入驱动jar包;如何导入可以参看:Java结合连接数据库进行查询操作
- 注册驱动;也就是加载驱动
Class.forName("com.mysql.cj.jdbc.Driver"); //加载驱动(不写也没有问题)
- 利用
DriverManager
获取数据库连接对象Connection
String url = "jdbc:mysql://localhost:3306/ou2? useSSL = false&serverTimezone = GMT"; //url地址语句
Connection connection = DriverManager.getConnection(url, "root", ""); //获取连接对象
- 定义sql语句
String sql = "insert into account (name,balance) values ('小绿',3000)"; //增加一条记录sql语句
- 用连接器对象connection获取sql执行sql语句的对象
Statement
Statement statement = connection.createStatement(); //获取SQL语句执行对象
- 执行sql语句;接受返回结果
int i = statement.executeUpdate(sql); //返回的是影响的行数
- 处理结果
- 释放资源
3.详解各个对象
DriverManager:驱动管理对象
该类的功能有两个;
注册驱动:告诉程序该实用哪一个数据库驱动jar;mysql5之后的驱动jar包可以省略注册驱动的步骤
原因就是jar包里面有一个文件会实现自动注册
另外一个功能就是调用getConnection
获取数据库连接
Connection:数据库连接对象
功能:获取执行sql的对象
Statement createStatement();
//获取执行sql的对象PreparedStatement prepareStatement(String sql)
;//获取预处理sql的对象
功能2:管理事务
- 开启事务:
setAutoCommit(boolean autoCommit) :
调用该方法设置参数为false,即开启事务 - 提交事务:
commit()
- 回滚事务:
rollback()
Statement:执行sql的对象
执行sql语句通常有两种:
int executeUpdate(String sql)
;通常都是执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句ResultSet executeQuery(String sql)
:执行DQL(select)语句;返回的是一个结果集
具体的例子
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcDemo_1 {
public static void main(String[] args) {
Class.forName("com.mysql.cj.jdbc.Driver"); //加载驱动(不写也没有问题)
String url = "jdbc:mysql://localhost:3306/ou2? useSSL = false&serverTimezone = GMT";
Connection connection = null; //connection对象
Statement statement = null; //SQL执行对象
//String sql = "insert into account (name,balance) values ('小绿',3000)"; //增加一条记录sql语句
//String sql = "update account set balance = 1500 where name = '小绿'"; //修改表中一条记录
String sql = "delete from account where NAME = '小绿'"; //删除表中一条记录
try {
connection = DriverManager.getConnection(url, "root", ""); //获取连接对象
statement = connection.createStatement(); //获取SQL语句执行对象
int i = statement.executeUpdate(sql); //返回的是影响的行数
if (i > 0) {
System.out.println("执行成功!");
} else {
System.out.println("执行失败!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (statement != null) { //为了避免statement为null的是时候执行释放会造成空指针异常那么就要对它进行一个判断
try {
statement.close(); //释放资源
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) { //同理
try {
connection.close(); //释放资源
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
ResultSet:结果集对象,封装查询结果
如果返回的是一个结果集;结果集里面封装的是表中的记录;有一个东西称为游标的东西;游标默认位置是指向表头的
因此需要调用next()
使游标向下移动一行;
判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
结果集可以调用getXxx(参数):获取数据;参数可以是列编号
或是列名称
例如;int getInt()
;String getString()
PreparedStatement:执行sql的对象
由于使用Statement处理SQL语句时,有些SQL的特殊关键字参与字符串拼接就会造成安全性问题
假如我的sql语句是这样定义的
String sql = "select * FROM user where user_name ='" + username + "' and password='" + password + "'";
当随机输入username;输入密码:a’ or ‘a’ = 'a
此时数据库没有该名用户记录也会返回ture;这就造成了严重的安全性问题
为了解决sql注入问题那么就可以使用PreparedStatement
对象来解决(一般都会用该对象)
使用预处理对象那么上述的SQL语句就变为
String sql = "select * FROM user where user_name = ? and password = ?";
preparedStatement = connection.prepareStatement(sql); //获取预处理对象并将sql语句放入
preparedStatement.setString(1, username); //给第一个? 赋值
preparedStatement.setString(2, password); //给第二个? 赋值
resultSet = preparedStatement.executeQuery(); //不需要传递sql语句
resultSet.next(); //如果有如果有下一行就返回true
使用PreparedStatement
执行sql对象的好处:可以防止SQL注入;效率更高
抽取JDBC工具类 : JDBCUtils(自定义的类)
创建该类的目的是为了简化书写;不想传递参数还要保证工具类的通用性(解决办法是使用配置文件)
那么如何实现?
首先创建一个util包;然后再创建一个JDBCUtils类;当然也可以不创建包直接创建类
然后创建一个配置文件xx.properties
然后代码实现JDBCUtils;每一步都有注释
package day_5.util;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String url; //私有静态变量
private static String user;
private static String password;
private static String Driver;
static { //文件的读取,只需要读取一次即可拿到这些值可以使用静态代码块
try {
Properties properties = new Properties(); //创建properties对象
ClassLoader classLoader = JDBCUtils.class.getClassLoader(); //获取类加载器
URL resource = classLoader.getResource("jdbc.properties"); //获取配置文件的url对象
String path = resource.getPath(); //url对象获取路径
properties.load(new FileReader(path)); //加载配置文件路径
url = properties.getProperty("url"); //获取数据
user = properties.getProperty("user");
password = properties.getProperty("password");
Driver = properties.getProperty("driver");
Class.forName(Driver); //注册驱动
} catch (IOException | ClassNotFoundException e) { //异常
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException { //返回一个连接对象
return DriverManager.getConnection(url, user, password);
}
public static void close(Statement sta, Connection con) { //带参数释放资源
if (sta != null) { //进行判断是否为null
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet res, Statement sta, Connection con) { //方法重载
if (sta != null) { //
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (res != null) {
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} //方法的重载
}
这样一来一个JDBC工具类就创建完成了;如果修改使用的数据库或者另外的驱动可以对配置文件进行修改即可;十分方便
JDBC控制事务
由于前面已经提及到事务所以这里直接使用例子进行示范;并使用上述创建的jdbc工具类
package day_5;
import day_5.util.JDBCUtils; //上述自定义创建的工具类
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JdbcDemo_6 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement1 = null;
PreparedStatement preparedStatement2 = null;
try {
connection = JDBCUtils.getConnection(); //获取连接对象
connection.setAutoCommit(false); //开启事务
String sql1 = "update account set balance = balance - ? where name = ?";
String sql2 = "update account set balance = balance + ? where name = ?";
preparedStatement1 = connection.prepareStatement(sql1);
preparedStatement2 = connection.prepareStatement(sql2);
preparedStatement1.setString(1, "500"); //第一个预处理赋值
preparedStatement1.setString(2, "小芳"); //第二个预处理赋值
preparedStatement2.setString(1, "500");
preparedStatement2.setString(2, "小红");
preparedStatement1.executeUpdate(); //预处理sql执行
//int i = 3 / 0; //手动添加异常
preparedStatement2.executeUpdate();
connection.commit();
} catch (Exception e) {
try {
if (connection != null) { //因为connection是有可能出现null的
connection.rollback(); //事务的回滚
}
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} finally { //释放资源
JDBCUtils.close(preparedStatement1, connection);
JDBCUtils.close(preparedStatement2, null); //没有就传个null
}
}
}
CET4P249
- purchase
- thesis
- telecommunications
- generation
- warfare
- consolidate
- reject
- dizzy
- ecology
- eternal
- deem