【Java】JDBC
JDBC
JDBC是用Java语言向数据库发送SQL。
在Java里专门为JDBC提供有一个模块(java.sql),里面有一个核心模块(java.sql),在JDBC里核心的组成就是DriverManager类,以及若干接口(Connection、Statement、PreparedStatement、ResultSet)。
对于JDBC的程序数据库访问也分为如下四种形式:
- JDBC-ODBC桥连接(淘汰了)
- JDBC链接:一般连接本地数据库。
- JDBC网络连接:通过特定的网络协议连接指定的数据库。
- JDBC协议连接:自己通过编写指定的协议操纵实现数据库。
JDBC工作原理
JDBC使用流程图
基本流程代码:
import java.sql.*;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//3.获取数据库链接对象
String url = "jdbc:mysql://127.0.0.1:3306/transport";
String user = "root";
String password = "111111";
Connection connection = DriverManager.getConnection(url,user,password);
//4.定义SQL语句
String sql = "insert into message values(1,'陕西西安')";
//5.获取执行sql的对象
Statement statement = connection.createStatement();
//6.执行sql
int count = statement.executeUpdate(sql);
//7.处理结果
System.out.println(count);
//8.释放资源
statement.close();
connection.close();
}
}
详解对象
DriverManager:驱动管理对象
功能:
- 注册驱动:告诉程序该使用哪个数据库驱动jar
- 获取数据库链接
- 方法:static connection getconnection(string url,string user,string password)
- 参数:
- ur1:指定连接的路径
- 语法:jdbc:mysql://ip地址(域名:端口号/款据库名称。
- 例子:jdbc:mysql://localhost:3306/db
- user:用户名
- password:密码
- ur1:指定连接的路径
Connection:数据库链接对象
功能:
- 获取执行sq1的对象
- statement createstatement()
- Preparedstatement preparestatement(string sql)
- 管理事务:
- 开后事务:setAutocommit(boolean autocommit):调用该方法设置参数为false,即开后事务
- 提交事务:commit()
- 回液事务:rollback()
Statement:执行sql对象
执行sql
- boolean execute(stringsql):可以执行任意的sql了解
- int executeupdate(String sql):执行DML(insert、update、delete)语句、DOL(create,alter、drop)语句
- 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功返回值>0的则执行成功,反之,则失败。
- Resultset executeQuery(string sql):执行DQL(select)语句
- 返回值:返回结果集对象。
import java.sql.*;
public class Main{
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/transport";
String user = "root";
String password = "password";
connection = DriverManager.getConnection(url,user,password);
//4.定义SQL语句
String sql = "insert into message values(1,'陕西西安')";
//5.获取执行sql的对象
statement = connection.createStatement();
//6.执行sql
int count = statement.executeUpdate(sql);
//7.处理结果
System.out.println(count);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//8.释放资源
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
Resultset:结果集对象
- boolean next():游标向下移动一行,判断当前行是否是最后一行未尾(是否有数据),如果是,则返回false,如果不是则返回true。
- getXxx(参数):获取数据
- Xxx():代表数据类型如:int getInt(),string getstring()
- 参数:
- int:代表列的编号,从1开始如:getstring(1)
- string:代表列名称。如:getInt("id")
- 使用步骤:
1.游标向下移动一行
2.判断是否有数据
3.获取数据
import java.sql.*;
public class JDBCdemo1 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet res = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/transport";
String user = "root";
String password = "111111";
connection = DriverManager.getConnection(url,user,password);
//4.定义SQL语句
//String sql = "insert into message values(2,'广东汕头')";
String sql = "select * from Message";
//5.获取执行sql的对象
statement = connection.createStatement();
//6.执行sql
res = statement.executeQuery(sql);
//7.处理结果
while(true == res.next()){//让指针向下移动一行
int id = res.getInt(1);
String address = res.getString(2);
System.out.println("id = " + id + " address = " + address);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//8.释放资源
if(res != null){
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
PreparedStatement:执行sql对象(功能更强大)
- SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
- 输入用户随便,输人密码:a' or 'a' = 'a
- sql:select * from user where username = 'fhdsjkf' and password = a' or 'a' = 'a
- 解决sq1注入问题:使用PreparedStatement对象来解决。
- 预编译的SQL:参数使用?作为占位符。
- 步骤:
- 导入驱动jar包
- 注册驱动
- 获取数据库连接对象
- 定义sq1
- 注意:定义SQL的时候使用?占位符
- 例子:select * from user where username = ?and password = ?;
- 获取执行sql语句的对象 Preparedstatement pstmt = Connection.preparestatement(string sql)
- 给?赋值:
- 方法:setXxx(参数1,参数2)
- 参数1:?的位置编号从1开始
- 参数2:?的值
- 执行sql,接受返回结果,不需要传递参数。
- 处理结果
- 释放资源
JDBCUtils自己写的JDBC的工具类
import java.sql.*;
public class JDBCUtils {
private static String url = "jdbc:mysql://127.0.0.1:3306/transport";
private static String user = "root";
private static String password = "111111";
private static String driver = "com.mysql.jdbc.Driver";
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return 连接对象
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
/**
* 释放资源
* @param res
* @param stmt
* @param conn
*/
public static void close(ResultSet res, Statement stmt, Connection conn){
if(res != null){
try {
res.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();
}
}
}
}
测试代码:
import java.sql.*;
public class JDBCdemo1 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet res = null;
try {
connection = JDBCUtils.getConnection();
String sql = "select * from Message";
statement = connection.createStatement();
res = statement.executeQuery(sql);
while(true == res.next()){
int id = res.getInt(1);
String address = res.getString(2);
System.out.println("id = " + id + " address = " + address);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(res,statement,connection);
}
}
}
JDBC控制事务:
- 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
- 操作:
- 开启事务
- 提交事务
- 回滚事务
- 使用Connection对象来管理事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 在执行sql之前开启事务
- 提交事务:commit()
- 当所有sql都执行完提交事务
- 回滚事务:rollback()
- 在catch中回滚事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
import java.sql.*;
public class JDBCdemo2 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
//2.定义sql
//2.1 张三 - 500
String sql1 = "update account set balance = balance - ? where id = ?";
//2.2 李四 + 500
String sql2 = "update account set balance = balance + ? where id = ?";
//3.获取执行sql对象
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
//4. 设置参数
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
//5.执行sql
pstmt1.executeUpdate();
// 手动制造异常
int i = 3/0;
pstmt2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
//事务回滚
try {
if(conn != null) {
conn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
JDBCUtils.close(pstmt1,conn);
JDBCUtils.close(pstmt2,null);
}
}
}
数据库连接池
概念:其实就是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会得连接对象归还给容器。
好处:
1. 节约资源
2. 用户访问高效
实现:
标准接口:Datasource javax.sql包下的
方法:
- 获取连接:getconnection();
- 归还连接:connection.close();如果连接对象connection是从连接池中获取的,那么调用该方法,则不会关闭连接。而是归还连接.