程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> JDBCMYSQL學習筆記(一)JDBC基本使用

JDBCMYSQL學習筆記(一)JDBC基本使用

編輯:MySQL綜合教程

JDBCMYSQL學習筆記(一)JDBC基本使用


1、JDBC簡介

SUN公司為了簡化、統一對數據庫的操作,定義了一套Java操作數據庫的規范,稱之為JDBC。 JDBC全稱為:Java Data Base Connectivity(java數據庫連接),它主要由接口組成。 組成JDBC的2個包:java.sql javax.sql

開發JDBC應用需要以上2個包的支持外,還需要導入相應JDBC的數據庫實現(即數據庫驅動)。

\

2、使用JDBC的步驟——第一個JDBC程序

需求:編程從user表中讀取數據,並打印在命令行窗口中。
(1) 搭建實驗環境 :
a、在mysql中創建一個數據庫,並創建user表,同時插入數據到表中。
b、新建一個Java工程,並導入數據庫驅動。
(2) 編寫程序,在程序中加載數據庫驅動

         a、方式一:DriverManager. registerDriver(Driver driver)
 
         b、方式二:Class.forName(“com.mysql.jdbc.Driver”);
(3) 建立連接(Connection)
Connection conn = DriverManager.getConnection(url,user,pass);

(4) 創建用於向數據庫發送SQL的Statement對象,並發送sql

         Statement st = conn.createStatement();
 
         ResultSet rs = st.excuteQuery(sql);

(5) 從代表結果集的ResultSet中取出數據,打印到命令行窗口

(6) 斷開與數據庫的連接,並釋放相關資源

dome:

import java.sql.*;

import com.sun.org.apache.regexp.internal.recompile;

public class dome {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws SQLException,ClassNotFoundException{
		// TODO Auto-generated method stub
		
		String url = "jdbc:mysql://localhost:3306/skyfin";
		String username = "root";
		String password = "skyfin";
		//1.加載驅動
		//DriverManager.registerDriver(new com.mysql.jdbc.Driver());

		Class.forName("com.mysql.jdbc.Driver");		//2獲取連接
Connection connection = DriverManager.getConnection(url,username,password);
	//3.獲取向數據庫發sql語句的statament對象
Statement stat = connection.createStatement();
//4.向數據庫發送sql,獲取數據庫返回的結果集
ResultSet rsResultSet = stat.executeQuery("select * from user");
//5.從結果集中獲取數據while (rsResultSet.next()) {System.out.println("id = "+ rsResultSet.getObject("id"));System.out.println("name = "+ rsResultSet.getObject("name"));
System.out.println("password = "+ rsResultSet.getObject("password"));}
 //6.釋放資源(釋放鏈接)rsResultSet.close();stat.close();connection.close();}}

3、DriverManager ——加載數據庫驅動

Jdbc程序中的DriverManager用於加載驅動,並創建與數據庫的鏈接,這個API的常用方法:

    DriverManager.registerDriver(new Driver());
    DriverManager.getConnection(url, user, password);
注意:在實際開發中並不推薦采用registerDriver方法注冊驅動。原因有二:
一、查看Driver的源代碼可以看到,如果采用此種方式,會導致驅動程序注冊兩次,也就是在內存中會有兩個Driver對象。
二、程序依賴mysql的api,脫離mysql的jar包,程序將無法編譯,將來程序切換底層數據庫將會非常麻煩。
推薦方式:
Class.forName(“com.mysql.jdbc.Driver”);
采用此種方式不會導致驅動對象在內存中重復出現,並且采用此種方式,程序僅僅只需要一個字符串,不需要依賴具體的驅動,使程序的靈活性更高。
同樣,在開發中也不建議采用具體的驅動類型指向getConnection方法返回的connection對象。

4、數據庫URL ——標識數據庫的位置

URL用於標識數據庫的位置,程序員通過URL地址告訴JDBC程序連接哪個數據庫,

MySql 數據庫的URL寫法為: jdbc:mysql:[]//localhost:3306/test ?參數名:參數值
\
常用數據庫URL地址的寫法:
Oracle:jdbc:oracle:thin:@localhost:1521:skyfin
SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=skyfin
MySql:jdbc:mysql://localhost:3306/skyfin
Mysql的url地址的簡寫形式: jdbc:mysql://skyfin
常用屬性:useUnicode=true&characterEncoding=UTF-8

jdbc:mysql://localhost:3306/test?user=root&password=&useUnicode=true&characterEncoding=gbk&autoReconnect=true&failOverReadOnly

5、Connection ——代表數據庫的鏈接

Jdbc程序中的Connection,它用於代表數據庫的鏈接。Connection 是數據庫編程中最重要的一個對象,客戶端與數據庫所有交互都是通過Connection 對象完成的,這個對象的常用方法:
(1) createStatement():創建向數據庫發送sql的statement對象。
(2) prepareStatement(sql) :創建向數據庫發送預編譯sql的PrepareSatement對象。
(3) prepareCall(sql):創建執行存儲過程的callableStatement對象。
(4) setAutoCommit(boolean autoCommit):設置事務是否自動提交。
(5) commit() :在鏈接上提交事務。
(6) rollback() :在此鏈接上回滾事務。

6、Statement ——向數據庫發送SQL語句

Jdbc程序中的Statement對象用於向數據庫發送SQL語句, Statement對象常用方法:
(1) executeQuery(String sql) :用於向數據庫發送查詢語句。
(2) executeUpdate(String sql):用於向數據庫發送insert、update或delete語句
(3) execute(String sql):用於向數據庫發送任意sql語句
(4) addBatch(String sql) :把多條sql語句放到一個批處理中。
(5) executeBatch():向數據庫發送一批sql語句執行。
(6) clearBatch() :清空此 Statement 對象的當前 SQL 命令列表。

7、ResultSet ——代表Sql語句的執行結果

Jdbc程序中的ResultSet用於代表Sql語句的執行結果。Resultset封裝執行結果時,采用的類似於表格的方式。ResultSet 對象維護了一個指向表格數據行的游標,初始的時候,游標在第一行之前,調用ResultSet.next() 方法,可以使游標指向具體的數據行,進行調用方法獲取該行的數據。

(1) ResultSet提供了對結果集進行滾動的方法:

a、next():移動到下一行
b、Previous():移動到前一行
c、absolute(int row):移動到指定行
d、beforeFirst():移動resultSet的最前面。
e、 afterLast() :移動到resultSet的最後面。

(2) ResultSet既然用於封裝執行結果的,所以該對象提供了用於獲取數據的get方法:

獲取任意類型的數據
getObject(int index)
getObject(string columnName)
獲取指定類型的數據,例如:
getString(int index)
getString(String columnName)
其他獲取指定類型數據的方法見下表:
常用數據類型轉換表:

 

\

 

8、釋放資源 ——釋放與數據庫進行交互的對象

Jdbc程序運行完後,切記要釋放程序在運行過程中,創建的那些與數據庫進行交互的對象,這些對象通常是ResultSet, Statement和Connection對象。
特別是Connection對象,它是非常稀有的資源,用完後必須馬上釋放,如果Connection不能及時、正確的關閉,極易導致系統宕機。Connection的使用原則是盡量晚創建,盡量早的釋放。
為確保資源釋放代碼能運行,資源釋放代碼也一定要放在finally語句中。

9、用JDBC對數據庫進行CRUD

jdbc中的statement對象用於向數據庫發送SQL語句,想完成對數據庫的增刪改查,只需要通過這個對象向數據庫發送增刪改查語句即可。
Statement對象的executeUpdate方法,用於向數據庫發送增、刪、改的sql語句,executeUpdate執行完後,將會返回一個int整數(即增刪改語句導致了數據庫幾行數據發生了變化)。
Statement.executeQuery方法用於向數據庫發送查詢語句,executeQuery方法返回代表查詢結果的ResultSet對象。

 

 

	public static void main(String[] args) throws SQLException,ClassNotFoundException{
		// TODO Auto-generated method stub
		
		String url = "jdbc:mysql://localhost:3306/skyfin";
		String username = "root";
		String password = "skyfin";
		//DriverManager.registerDriver(new com.mysql.jdbc.Driver());

		Class.forName("com.mysql.jdbc.Driver");

		Connection  connection = DriverManager.getConnection(url,username,password);
		
		Statement stat = connection.createStatement();
		
		/*
		 * 執行查找操作
		 */
		ResultSet rsResultSet = stat.executeQuery("select * from user");
		
		while (rsResultSet.next()) {
			System.out.println("id = "+ rsResultSet.getObject("id"));
			System.out.println("name = "+ rsResultSet.getObject("name"));
			System.out.println("password = "+ rsResultSet.getObject("password"));
			
		}

		
		/*
		 * 執行插入操作
		 */
		String sql = "insert into user(id,name,password) value(6,"+"'staff'"+","+"'staff'"+")";
		System.out.println(sql);
		int statentnum = stat.executeUpdate(sql);
		if (statentnum>0) {
			System.out.println("insert ok");
		}
		
		/*
		 * 執行更新操作
		 */
		sql = "update user set name = 'skstaff' where name = 'staff'";
		System.out.println(sql);
		statentnum = stat.executeUpdate(sql);
		if (statentnum>0) {
			System.out.println("update ok");
		}
		
		/*
		 * 執行刪除操作
		 */
		sql = "delete from user where name = 'skstaff'";
		System.out.println(sql);
		statentnum = stat.executeUpdate(sql);
		if (statentnum>0) {
			System.out.println("delete ok");
		}
		/*
		 * 資源的釋放
		 */
		rsResultSet.close();
		stat.close();
		connection.close();
	}

10、用JDBC的PreparedStatement啟動事務使用批處理executeBatch()

JDBC使用MySQL處理大數據的時候,自然而然的想到要使用批處理,
普通的執行過程是:每處理一條數據,就訪問一次數據庫;
而批處理是:累積到一定數量,再一次性提交到數據庫,減少了與數據庫的交互次數,所以效率會大大提高
至於事務:事務指邏輯上的一組操作,組成這組操作的各個單元,要不全部成功,要不全部不成功,默認是關閉事務的。

1. PreparedStatement使用批處理 executeBatch()

1.1. 不使用executeBatch(),而使用executeUpdate(),速度很慢

 

	public static void main(String[] args) throws  SQLException,ClassNotFoundException{
		// TODO Auto-generated method stub
		
		String url = "jdbc:mysql://localhost:3306/skyfin";
		String username = "root";
		String password = "skyfin";
		//DriverManager.registerDriver(new com.mysql.jdbc.Driver());

		Class.forName("com.mysql.jdbc.Driver");

		Connection  connection = DriverManager.getConnection(url,username,password);
		String sql = "insert into user1(id,name) value(?,?)";
		PreparedStatement preparedStatement = connection.prepareStatement(sql);
		for(int i = 0;i<10000;i++){
			preparedStatement.setInt(1, i);
			preparedStatement.setString(2, "skyfin"+i);
			preparedStatement.executeUpdate();
		}
	}

 

1.2. 而使用executeBatch()

	public static void main(String[] args) throws  SQLException,ClassNotFoundException{
		// TODO Auto-generated method stub
		
		String url = "jdbc:mysql://localhost:3306/skyfin";
		String username = "root";
		String password = "skyfin";
		//DriverManager.registerDriver(new com.mysql.jdbc.Driver());

		Class.forName("com.mysql.jdbc.Driver");

		Connection  connection = DriverManager.getConnection(url,username,password);
		String sql = "insert into user1(id,name) value(?,?)";
		PreparedStatement preparedStatement = connection.prepareStatement(sql);
		for(int i = 0;i<10000;i++){
			preparedStatement.setInt(1, i);
			preparedStatement.setString(2, "skyfin"+i);
			//preparedStatement.executeUpdate();
			/*
			 * 使用executeBatch()
			 */
			preparedStatement.addBatch();
		}
		//執行批處理
		preparedStatement.executeBatch();
	}

 

注意:1. 如果使用了 addBatch() -> executeBatch() 還是很慢,那就得使用到這個參數了rewriteBatchedStatements=true (啟動批處理操作)
在數據庫連接URL後面加上這個參數: String dbUrl = "jdbc:mysql://localhost:3306/User? rewriteBatchedStatements=true";
2. 在代碼中,pstmt的位置不能亂放,必須放在循環體外

2. 啟用事務處理

 

	public static void main(String[] args) throws  SQLException,ClassNotFoundException{
		// TODO Auto-generated method stub
		
		String url = "jdbc:mysql://localhost:3306/skyfin";
		String username = "root";
		String password = "skyfin";
		//DriverManager.registerDriver(new com.mysql.jdbc.Driver());

		Class.forName("com.mysql.jdbc.Driver");

		Connection  connection = DriverManager.getConnection(url,username,password);
		//關閉自動提交
		connection.setAutoCommit(false);
		String sql = "update user1 set name = ?where id = ?";
		PreparedStatement preparedStatement = connection.prepareStatement(sql);
		for(int i = 0;i<10000;i++){
			
			preparedStatement.setString(1, "loco"+i);
			preparedStatement.setInt(2, i);
			
			//preparedStatement.executeUpdate();
			/*
			 * 使用executeBatch()
			 */
			preparedStatement.addBatch();
		}
		//執行批處理
		preparedStatement.executeBatch();
		preparedStatement.close();
		//執行完後手動提交事務
		connection.commit();
		//打開自動提交
		connection.setAutoCommit(true);
		connection.close();
	}

 

3. 事務和批處理混合使用

	public static void main(String[] args) throws  SQLException,ClassNotFoundException{
		// TODO Auto-generated method stub
		
		String url = "jdbc:mysql://localhost:3306/skyfin";
		String username = "root";
		String password = "skyfin";
		//DriverManager.registerDriver(new com.mysql.jdbc.Driver());

		Class.forName("com.mysql.jdbc.Driver");

		Connection  connection = DriverManager.getConnection(url,username,password);
		//關閉自動提交
		connection.setAutoCommit(false);
		String sql = "update user1 set name = ?where id = ?";
		PreparedStatement preparedStatement = connection.prepareStatement(sql);
		for(int i = 0;i<10000;i++){
			
			preparedStatement.setString(1, "skyfin"+i);
			preparedStatement.setInt(2, i);
			
			//preparedStatement.executeUpdate();
			/*
			 * 使用executeBatch()
			 */
			if (i>0&&i%500 == 0) {
				preparedStatement.executeBatch();
				//如果不想出錯後,完全沒保留數據,則可以沒執行一次提交一次,但得保證數據不會重復
				connection.commit();
			}
			preparedStatement.addBatch();
		}
		//執行批處理
		preparedStatement.executeBatch();
		preparedStatement.close();
		//執行完後手動提交事務
		connection.commit();
		//打開自動提交
		connection.setAutoCommit(true);
		connection.close();
	}

11、SQL 注入的防范

SQL 注入是用戶利用某些系統沒有對輸入數據進行充分的檢查,從而進行惡意破壞的行為。
1、statement存在sql注入攻擊問題,例如登陸用戶名采用' or 1=1 or username=‘
2、對於防范 SQL 注入,可以采用PreparedStatement取代Statement。
備注:本例只是最基本的防止SQL注入方式,其他情況還請查閱資料。

12、PreparedStatement

PreperedStatement是Statement的孩子,它的實例對象可以通過調用Connection.preparedStatement()方法獲得,相對於Statement對象而言的優勢:
(1) 防止SQL注入:PreperedStatement可以避免SQL注入的問題。
(2) 預編譯SQL語句:Statement會使數據庫頻繁編譯SQL,可能造成數據庫緩沖區溢出。PreparedStatement 可對SQL進行預編譯,從而提高數據庫的執行效率。
(3) 使用占位符簡化語句:並且PreperedStatement對於sql中的參數,允許使用占位符的形式進行替換,簡化sql語句的編寫。 (例如多次循環插入數據)

 

 

public List getAll(){
 
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try{
              conn = JdbcUtils.getConnection();
              String sql = "select * from customer";
              st = conn.prepareStatement(sql);
              rs = st.executeQuery();
              List list = new ArrayList();
              while(rs.next()){
 
                    Customer c = new Customer();
 
                    c.setBirthday(rs.getDate("birthday"));
 
                    c.setCellphone(rs.getString("cellphone"));
 
                    c.setDescription(rs.getString("description"));
 
                    c.setEmail(rs.getString("email"));
 
                    c.setGender(rs.getString("gender"));
 
                    c.setId(rs.getString("id"));
 
                    c.setName(rs.getString("name"));
 
                    c.setPreference(rs.getString("preference"));
 
                    c.setType(rs.getString("type"));
 
                    list.add(c);
              }
              return list;
        }catch (Exception e) {
              throw new DaoException(e);
        }finally{
              JdbcUtils.release(conn, st, rs);
        }
  }
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved