1 JDBC入門
1.1 回顧
之前操作mysql數據庫:
1)使用mysql客戶端工具
2)使用客戶端連接mysql服務器
3)發送sql語句到mysql服務器,執行
1.2 什麼是JDBC?
使用java程序發送sql語句到數據庫服務器端執行,這叫用到了JDBC技術!!!!
jdbc是Oracle-Sun公司設計的一套專門用於java程序操作數據庫的接口。
1.3 使用jdbc發送sql條件
連接mysql數據庫:
數據庫主機
端口
數據庫用戶名
數據庫密碼
連接的數據庫
1.4 JDBC的核心API
|-Driver接口: 數據庫驅動程序的接口,所有具體數據庫廠商需要的驅動程序需要實現此接口。
Connection connect(String url, Properties info) 用於獲取數據庫連接
案例:演示三種連接數據庫的方式
|-Connection接口:與具體的數據庫的連接對象。
Statement createStatement() 創建一個靜態sql語句對象
PreparedStatement prepareStatement(String sql) 創建預編譯的sql語句對象
CallableStatement prepareCall(String sql) 創建存儲過程的sql語句對象
|-Statement接口:用於執行靜態 SQL 語句
int executeUpdate(String sql) 執行更新操作的sql語句 (create/alter/drop) DDL語句
(insert/update/delete)DML語句
ResultSet executeQuery(String sql) 執行查詢操作的sql語句
(select)(DQL查詢語句)
|- PreparedStatement接口:用於執行預編譯的 SQL 語句(是Statement的子接口)
int executeUpdate() 執行更新操作的sql語句
ResultSet executeQuery() 執行查詢操作的sql語句
|- CallableStatement接口:用於執行 SQL 存儲過程的接口(是PreparedStatement的子接口)
ResultSet executeQuery() 執行存儲過程的sql語句
|- ResultSet接口:結果集對象。 存儲所有數據庫查詢的結果,用該對象進行數據遍歷。
boolean next() : 把光標移動到下一行。如果下一行有數據,返回true,如果沒有下一行數據,返回false。
getXXX(列索引|列字段名稱): 獲取字段的數據
2 Statement對象執行SQL操作
2.1 執行DDL操作
/**
* 通過jdbc執行DDL語句
* @author APPle
*/
public class Demo1 {
//數據庫的連接的URL
private static String url = "jdbc:mysql://localhost:3306/day17";
//數據庫用戶名
private static String user = "root";
//數據庫密碼
private static String password = "root";
public static void main(String[] args){
Connection conn = null;
Statement stmt = null;
try {
//1.驅動驅動程序
Class.forName("com.mysql.jdbc.Driver");
//2.從驅動程序管理類獲取連接
conn = DriverManager.getConnection(url, user, password);
//3.通過Connection對象獲取Statement對象
stmt = conn.createStatement();
//4.準備sql語句
String sql = "CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),gender VARCHAR(2))";
//5.執行sql語句,返回結果
int count = stmt.executeUpdate(sql);
System.out.println("影響了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
//6.關閉資源(先關閉statement,再關閉connection)
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
2.2 執行DML操作
/**
* 通過jdbc執行DML語句(insert/update/delete)
* @author APPle
*
*/
public class Demo2 {
//數據庫的連接的URL
private static String url = "jdbc:mysql://localhost:3306/day17";
//數據庫用戶名
private static String user = "root";
//數據庫密碼
private static String password = "root";
/**
* 執行插入操作
*/
@Test
public void test1(){
Connection conn = null;
Statement stmt = null;
try {
//註冊驅動
Class.forName("com.mysql.jdbc.Driver");
//獲取連接
conn = DriverManager.getConnection(url, user, password);
//創建Statment對象
stmt = conn.createStatement();
//準備sql
String sql = "INSERT INTO student(NAME,gender) VALUES('張三','男')";
//執行sql,返回結果
int count = stmt.executeUpdate(sql);
System.out.println("影響了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
//關閉資源
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
/**
* 執行更新操作
*/
@Test
public void test2(){
Connection conn = null;
Statement stmt = null;
//聲明外部變量
String name = "陳六";
int id=2;
try {
//註冊驅動
Class.forName("com.mysql.jdbc.Driver");
//獲取連接
conn = DriverManager.getConnection(url, user, password);
//創建Statment對象
stmt = conn.createStatement();
//準備sql
String sql = "UPDATE student SET NAME='"+name+"' WHERE id="+id+""; //變量和String拼接sql
//執行sql,返回結果
int count = stmt.executeUpdate(sql);
System.out.println("影響了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
//關閉資源
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
/**
* 執行刪除操作
*/
@Test
public void test3(){
Connection conn = null;
Statement stmt = null;
//聲明外部變量
int id=2;
try {
//註冊驅動
Class.forName("com.mysql.jdbc.Driver");
//獲取連接
conn = DriverManager.getConnection(url, user, password);
//創建Statment對象
stmt = conn.createStatement();
//準備sql
String sql = "DELETE FROM student WHERE id="+id+""; //變量和String拼接sql
//執行sql,返回結果
int count = stmt.executeUpdate(sql);
System.out.println("影響了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
//關閉資源
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
2.3 執行DQL查詢操作
/**
* 使用jdbc執行DQL語句(select)
* @author APPle
*
*/
public class Demo3 {
//數據庫的連接的URL
private static String url = "jdbc:mysql://localhost:3306/day17";
//數據庫用戶名
private static String user = "root";
//數據庫密碼
private static String password = "root";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//註冊驅動
Class.forName("com.mysql.jdbc.Driver");
//獲取連接
conn = DriverManager.getConnection(url, user, password);
//創建Statement對象
stmt = conn.createStatement();
//準備sql
String sql = "SELECT * FROM student";
rs = stmt.executeQuery(sql);
//移動光標到下一行
//rs.next();
/**
* 注意:
* 1)如果光標在第一行之前,使用rs.getXX()獲取列值,報錯:Before start of result set
* 2)如果光標在最後一行之後,使用rs.getXX()獲取列值,報錯:After end of result set
*/
//獲取列值
/*if(rs.next()){
//使用列索引
int id = rs.getInt(1);
String name = rs.getString(2);
String gender = rs.getString(3);
//使用列名稱
int id = rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+"\t"+name+"\t"+gender+"\t");
}*/
//迭代結果集
while(rs.next()){
//使用列索引
/*
int id = rs.getInt(1);
String name = rs.getString(2);
String gender = rs.getString(3);
*/
//使用列名稱
int id = rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+"\t"+name+"\t"+gender+"\t");
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
if(rs!=null)
try {
rs.close();
} catch (SQLException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
}
//關閉資源
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
2.4jdbc工具類的抽取
private static String url = "jdbc:mysql://localhost:3306/day18";
private static String user = "root";
private static String password = "root";
private static String className = "com.mysql.jdbc.Driver";
static{
//註冊驅動,註冊一次就可以了
//註冊驅動
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//獲取連接
public static Connection getConnection(){
try {
//獲取連接
Connection conn = DriverManager.getConnection(url, user, password);
//返回conn
return conn;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
//釋放資源
public static void close(ResultSet rs,Statement stmt,Connection conn){
//先判空後釋放
if (rs!=null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
if (stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
}
2.5 課堂練習
1.使用jdbc創建一張員工表
員工表字段:編號,姓名,性別,年齡,職位,郵箱,電話
2.使用jdbc對員工表執行以下操作:
1)插入一條數據
2)修改一條數據
3)刪除一條數據
4)查詢並打印所有員工數據
3 PreparedStatement對象執行SQL操作
/**
* 使用PreparedStatement執行sql語句
* @author APPle
*
*/
public class Demo1 {
/**
* 插入操作
*/
@Test
public void test1(){
Connection conn = null;
PreparedStatement stmt = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)"; //預編譯sql:使用?號代替參數值。一個?號代表一個參數值
//創建PreparedStatement對象,執行預編譯的sql語句
stmt = conn.prepareStatement(sql);
//設置參數
/**
* 參數一: 參數位置。從1開始
* 參數二: 參數實際值
* 注意: 所有參數必須要賦值
*/
stmt.setString(1, "rose");
stmt.setString(2, "女");
//發送參數,執行sql語句
int count = stmt.executeUpdate();
System.out.println(count);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
//關閉資源
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 修改操作
*/
@Test
public void test2(){
Connection conn = null;
PreparedStatement stmt = null;
//聲明變量
String name = "jacky";
int id = 8;
try{
//獲取連接
conn = JdbcUtil.getConnection();
String sql = "UPDATE student SET NAME=? WHERE id=?"; //預編譯sql:使用?號代替參數值。一個?號代表一個參數值
//創建PreparedStatement對象,執行預編譯的sql語句
stmt = conn.prepareStatement(sql);
//設置參數
stmt.setString(1,name);
stmt.setInt(2, id);
//發送參數,執行sql語句
int count = stmt.executeUpdate();
System.out.println(count);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
//關閉資源
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 刪除操作
*/
@Test
public void test3(){
Connection conn = null;
PreparedStatement stmt = null;
//聲明變量
int id = 8;
try{
//獲取連接
conn = JdbcUtil.getConnection();
String sql = "DELETE FROM student WHERE id=?"; //預編譯sql:使用?號代替參數值。一個?號代表一個參數值
//創建PreparedStatement對象,執行預編譯的sql語句
stmt = conn.prepareStatement(sql);
//設置參數
//任何類型都可以使用setObject進行賦值
stmt.setObject(1, id);
//發送參數,執行sql語句
int count = stmt.executeUpdate();
System.out.println(count);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
//關閉資源
JdbcUtil.close(conn, stmt, null);
}
}
/**
* 查詢操作
*/
@Test
public void test4(){
Connection conn = null;
PreparedStatement stmt = null;
//聲明變量
String name = "張%";
try{
//獲取連接
conn = JdbcUtil.getConnection();
String sql = "SELECT * FROM student WHERE NAME LIKE ?";
//創建PreparedStatement,預編譯sql語句
stmt = conn.prepareStatement(sql);
//設置參數
stmt.setObject(1, name);
//發送參數,執行sql,返回結果集
ResultSet rs = stmt.executeQuery();
//遍歷結果集
while(rs.next()){
int id = rs.getInt("id");
String nameStr = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+"\t"+nameStr+"\t"+gender+"\t");
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
//關閉資源
JdbcUtil.close(conn, stmt, null);
}
}
}
Statement和PreparedStatement的區別==========================================
一、語法結構不同
1)Statment執行靜態sql語句,且sql可以拼接。
2)PreparedStatement可以先執行預編譯的sql語句,在預編譯sql語句中使用?進行參數佔位,後面在進行參數賦值
二、原理不同
1)Statement不能進行sql緩存
2)而PreparedStatement可以進行sql緩存,執行效率會比Statement快!!!
三、安全性不同
1)Statement存在sql注入的風險(使用登錄註冊講解sql注入)
2)而PreparedStatement可以有效防止用戶注入。
– 創建一張user表(sql注入)
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
PASSWORD VARCHAR(20)
);
– 給用戶表中插入數據
INSERT INTO USER(NAME,PASSWORD) VALUES(‘james’,’123456’);
INSERT INTO USER(NAME,PASSWORD) VALUES(‘mayun’,’123456’);
– 查詢表
SELECT * FROM USER WHERE NAME=’james’ AND PASSWORD=’123456’;
– 查詢全部表,基於肯定條件
SELECT * FROM USER WHERE 1=1;
– 查詢全張表給予否定條件
SELECT * FROM USER WHERE 1<>1;
– 查詢表(sql注入)
SELECT * FROM USER WHERE NAME='james' OR 1=1 ;-- ' AND PASSWORD='123456';
4 CallableStatement對象執行存儲過程
4.1 執行帶輸入參數的存儲過程
/**
* 執行帶有輸入參數存儲過程
*/
@Test
public void test1(){
Connection conn = null;
CallableStatement stmt = null;
ResultSet rs = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
//創建CallableStatement對象
String sql = "CALL pro_findById(?)";//預編譯sql、可以帶?號
//執行預編譯的sql
stmt = conn.prepareCall(sql);
//設置參數
stmt.setInt(1, 4);
//發送參數,執行sql,返回結果
rs = stmt.executeQuery();// 注意: 執行存儲過程必須使用exeuteQuery!!!!
//遍歷結果
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
System.out.println(id+"\t"+name+"\t"+gender+"\t");
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
//關閉資源
JdbcUtil.close(conn, stmt, rs);
}
}
4.2 執行帶有輸出參數的存儲過程
/**
* 執行帶有輸出參數存儲過程
*/
@Test
public void test2(){
Connection conn = null;
CallableStatement stmt = null;
try{
//獲取連接
conn = JdbcUtil.getConnection();
String sql = "CALL pro_findById2(?,?)"; // 第一個參數時輸入參數,第二個參數是輸出參數
//創建CallableStatement對象
stmt = conn.prepareCall(sql);
//設置輸入參數
stmt.setObject(1, 4);
//註冊一個輸出參數
/**
* 參數一: 參數位置
* 參數二: 表示存儲過程中的OUT參數的數據庫類型
*/
stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
//發送參數,執行存儲過程
stmt.executeQuery();
/**
* 如何獲取存儲過程的返回值:OUT參數值。使用getXXX方法
*/
String name = stmt.getString(2);//和預編譯語句中的參數位置保持一致!!!!
System.out.println("結果:"+name);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}finally{
//關閉資源
JdbcUtil.close(conn, stmt, null);
}
}
5 優化jdbc工具類
private static String url = null;
private static String user = null;
private static String password = null;
private static String className = null;
static{
//註冊驅動,註冊一次就可以了
//註冊驅動
try {
//給成員變量賦值,將文件中的鍵值對加載到properties集合中
Properties prop = new Properties();
InputStream in = new FileInputStream("db.properties");
prop.load(in);
url = prop.getProperty("url");
user = prop.getProperty("user");
password = prop.getProperty("password");
className = prop.getProperty("className");
System.out.println(url);
System.out.println(user);
System.out.println(password);
System.out.println(className);
Class.forName(className);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//獲取連接
public static Connection getConnection(){
try {
//獲取連接
Connection conn = DriverManager.getConnection(url, user, password);
//返回conn
return conn;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
//釋放資源
public static void close(ResultSet rs,Statement stmt,Connection conn){
//先判空後釋放
if (rs!=null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
if (stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
}
}