數據庫操作之PreparedStatement的使用


PreparedStatement的使用

1.1 PreparedStatement介紹

  • 可以通過調用 Connection 對象的 preparedStatement(String sql) 方法獲取 PreparedStatement 對象

  • PreparedStatement 接口是 Statement 的子接口,它表示一條預編譯過的 SQL 語句

  • PreparedStatement 對象所代表的 SQL 語句中的參數用問號(?)來表示,調用 PreparedStatement 對象的 setXxx() 方法來設置這些參數. setXxx() 方法有兩個參數,第一個參數是要設置的 SQL 語句中的參數的索引(從 1 開始),第二個是設置的 SQL 語句中的參數的值

1.2 PreparedStatement vs Statement

  • 代碼的可讀性和可維護性。

  • PreparedStatement 能最大可能提高性能:

    • DBServer會對預編譯語句提供性能優化。因為預編譯語句有可能被重復調用,所以語句在被DBServer的編譯器編譯后的執行代碼被緩存下來,那么下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行代碼中就會得到執行。
    • 在statement語句中,即使是相同操作但因為數據內容不一樣,所以整個語句本身不能匹配,沒有緩存語句的意義.事實是沒有數據庫會對普通語句編譯后的執行代碼緩存。這樣每執行一次都要對傳入的語句編譯一次。
    • (語法檢查,語義檢查,翻譯成二進制命令,緩存)
  • PreparedStatement 可以防止 SQL 注入

1.3 ORM思想(object relational mapping)

  • 一個數據表對應一個java類
  • 表中的一條記錄對應java類的一個對象
  • 表中的一個字段對應java類的一個屬性

sql是需要結合列名和表的屬性名來寫。注意起別名。

Java與SQL對應數據類型轉換表
Java類型 SQL類型
boolean BIT
byte TINYINT
short SMALLINT
int INTEGER
long BIGINT
String CHAR,VARCHAR,LONGVARCHAR
byte array BINARY , VAR BINARY
java.sql.Date DATE
java.sql.Time TIME
java.sql.Timestamp TIMESTAMP

1.4 使用PreparedStatement實現增、刪、改操作

	//通用的增、刪、改操作(體現一:增、刪、改 ; 體現二:針對於不同的表)
	public void update(String sql,Object ... args){
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			//1.獲取數據庫的連接
			conn = JDBCUtils.getConnection();
			
			//2.獲取PreparedStatement的實例 (或:預編譯sql語句)
			ps = conn.prepareStatement(sql);
			//3.填充占位符
			for(int i = 0;i < args.length;i++){
				ps.setObject(i + 1, args[i]);
			}
			
			//4.執行sql語句
			ps.execute();
		} catch (Exception e) {
			
			e.printStackTrace();
		}finally{
			//5.關閉資源
			JDBCUtils.closeResource(conn, ps);
			
		}
	}

1.5 使用PreparedStatement實現查詢操作

	// 通用的針對於不同表的查詢:返回一個對象 
	public <T> T getInstance(Class<T> clazz, String sql, Object... args) {

		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			// 1.獲取數據庫連接
			conn = JDBCUtils.getConnection();

			// 2.預編譯sql語句,得到PreparedStatement對象
			ps = conn.prepareStatement(sql);

			// 3.填充占位符
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}

			// 4.執行executeQuery(),得到結果集:ResultSet
			rs = ps.executeQuery();

			// 5.得到結果集的元數據:ResultSetMetaData
			ResultSetMetaData rsmd = rs.getMetaData();

			// 6.1通過ResultSetMetaData得到columnCount,columnLabel;通過ResultSet得到列值
			int columnCount = rsmd.getColumnCount();
			if (rs.next()) {
				T t = clazz.newInstance();
				for (int i = 0; i < columnCount; i++) {// 遍歷每一個列

					// 獲取列值
					Object columnVal = rs.getObject(i + 1);
					// 獲取列的別名:列的別名,使用類的屬性名充當
					String columnLabel = rsmd.getColumnLabel(i + 1);
					// 6.2使用反射,給對象的相應屬性賦值
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(t, columnVal);

				}

				return t;

			}
		} catch (Exception e) {

			e.printStackTrace();
		} finally {
			// 7.關閉資源
			JDBCUtils.closeResource(conn, ps, rs);
		}

		return null;

	}

說明:使用PreparedStatement實現的查詢操作可以替換Statement實現的查詢操作,解決Statement拼串和SQL注入問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM