程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 【java】對數據庫操作的那些事(包括數據庫中的預處理)

【java】對數據庫操作的那些事(包括數據庫中的預處理)

編輯:MySQL綜合教程

【java】對數據庫操作的那些事(包括數據庫中的預處理)


一、連接問題

前面剛介紹了怎麼連接數據庫,也寫了相應的模板,但是它的可維護性非常差,那麼怎麼解決這個問題呢?

首先寫一個配置文件jdbc.properties

## MySQL
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/hncu?useUnicode=true&characterEncoding=UTF-8
username=root
password=1234

## Oracle
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@192.168.31.12:1521:orcl
#username=scott
#password=tiger

然後創建一個生成連接的工廠ConnFactory .java

 

 

package cn.hncu.hibernate0;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

public class ConnFactory {
	private static Connection conn;
	static {
		try {
			//讀取配置文件
			Properties p = new Properties();
			p.load(ConnFactory.class.getClassLoader().getResourceAsStream("jdbc.properties"));
			String driver = p.getProperty("driver");
			String url = p.getProperty("url");
			String username = p.getProperty("username");
			String pwd = p.getProperty("password");
			
			Class.forName(driver);
			conn = DriverManager.getConnection(url,username,pwd);
			System.out.println("已連接到數據庫..."+conn);
		} catch (Exception e) {
			throw new RuntimeException("讀取配置文件失敗", e);
		}
	}
	public static Connection getConn(){
		return conn;
	}
	public static void main(String[] args) {
		getConn();
	}
}
最後直接通過ConnFactory.getConn()獲得。這要做的好處,當改變所要連接的數據庫類型時,只需要修改配置文件中的內容即可。

 

二、講解getXXX()方法

 

	@Test
	public void getXXXDemo() throws Exception{
		Statement st = ConnFactory.getConn().createStatement();
		String sql = "select * from book";
		ResultSet rs = st.executeQuery(sql);
		while(rs.next()){
			Integer id = rs.getInt(1);//這裡的1表示數據表中的第一列,下面同理
			String name = rs.getString(2);
			//Double price = (Double)rs.getObject(3);//出異常,因為內部是采用BigDecimal來處理
			Double price = rs.getDouble(3);
			Object dateTime = rs.getObject(4);//把日期和時間作為一個整體讀取出來
			System.out.println(id+","+name+","+price+","+dateTime);
			
			String strDateTime = dateTime.toString();
			System.out.println(strDateTime);
			strDateTime = rs.getDate(4)+"--"+rs.getTime(4);//日期和時間可以單獨獲取
			System.out.println(":::"+strDateTime);
		}
		ConnFactory.getConn().close();
	}
注:對於自動增長列,刪除之後再插入新記錄,序號不會回頭,繼續往前增長。即中間會出現空號

 

三、講解Statement中的三個executeXXX()方法

1、executeQuery: 只能執行select語句

2、executeUpdate: 可以執行insert、delete和update語句,但不能執行select

3、execute:增刪改查的4種(任意)語句都能執行。該方法若執行非select語句時返回false,執行select語句時返回true,且st對象會緩存該次查詢的結果,我

們可通過ResultSet rs = st.getResultSet()來獲得結果集

	@Test
	public void executeXXXDemo() throws Exception{
		Statement st = ConnFactory.getConn().createStatement();
	    String sql = "select * from book";
		//String sql = "insert into book(name,price,pub) values('軟件工程',22.35,'2015-12-05 22:12:23')";
		//String sql = "update book set price=38.88 where name='軟件工程'";
		//String sql = "delete from book where name='軟件工程'";
	    //st.executeQuery(sql);
		//st.executeUpdate(sql);
		boolean boo = st.execute(sql);
		
		if(boo){
			ResultSet rs = st.getResultSet();
			while(rs.next()){
				System.out.println(rs.getObject(2));
			}
		}
	}

 

四、數據庫查詢時防黑技術(預處理語句)

案例、用戶登錄(通過用戶輸入信息來拼接sql語句----很危險)

 

	@Test//用戶登錄    
	public void login() throws Exception{
		Connection con = ConnFactory.getConn();
		Statement st = con.createStatement();
		Scanner sc = new Scanner(System.in);
		int id = sc.nextInt(); sc.nextLine();
		String name = sc.nextLine();
		String sql = "select count(*) from stud where id="+id+" and sname='"+name+"'";
		System.out.println("sql:"+sql);
		ResultSet rs = st.executeQuery(sql);
		rs.next();
		int a = rs.getInt(1);
		if(a<=0){
			System.out.println("登錄不成功");
		}else{
			System.out.println("登錄成功");
		}
		
		con.close();	   
	}
黑的方法,輸入:1002(回車) 1' or '1'='1
因此:如果需要用 用戶輸入的信息 來拼接 sql語句,就不能用statement,否則用戶可以通過構建where子句中的一個true條件來突破防護對於上面的情

 

況,應該用PreparedStatement來解決!

	@Test//用戶登錄     黑:1002(回車)   1' or '1'='1
	public void login2() throws Exception{
		Scanner sc = new Scanner(System.in);
		
		Connection con = ConnFactory.getConn();
		String sql = "select count(*) from stud where id=? and sname=?";//需要用戶輸入的地方,用占位符('?')來代替,然後在後續通過設參來給占位符賦值
		PreparedStatement pst = con.prepareStatement(sql);
		//設置參數
		int id = sc.nextInt(); sc.nextLine();
		pst.setInt(1, id); //參數1----代表第1個占位符
		String name = sc.nextLine();
		pst.setString(2, name);//參數2
		
		ResultSet rs = pst.executeQuery();
		
		rs.next();
		int a = rs.getInt(1);
		if(a<=0){
			System.out.println("登錄不成功");
		}else{
			System.out.println("登錄成功");
		}
		
		con.close();	   
	}

 

五、獲取自動增長列(如id)

	@Test //演示獲取自動增長列如id
	public void saveAuto() throws Exception{
		Connection con = ConnFactory.getConn();
		String sql = "insert into book(name,price,pub) values('JavaEE',100.8,'2013-06-12 08:30:30')";
		Statement st = con.createStatement();
		
		//st.executeUpdate(sql);
		st.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);
		ResultSet rs = st.getGeneratedKeys();//裡面封裝了自動生成的所有值
		if(rs.next()){
			int id = rs.getInt(1);//獲取第1個自動增長列
			System.out.println("自動增長的id:"+id);
		}
		System.out.println("-----------------");
		
		//預處理語句
		sql =  "insert into book(name,price) values(?,?)";
		PreparedStatement pst = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
		pst.setString(1, "計算機基礎");
		pst.setDouble(2, 28);
		pst.executeUpdate();
		ResultSet rs2 = pst.getGeneratedKeys();//裡面封裝了自動生成的所有值
		if(rs2.next()){
			int id = rs2.getInt(1);//獲取第1個自動增長列
			System.out.println("自動增長的id:"+id);
		}
	}


六、演示批處理語句

 

public void batch() throws Exception{
		Connection con = ConnFactory.getConn();
		String sql = "insert into book(name,price,pub) values('JavaEE',100.8,'2015-06-12 08:30:30')";
		Statement st = con.createStatement();
		for(int i=0;i<10;i++){
			st.addBatch(sql);
		}
		sql = "update book set price=price*1.1 where price>100";
		st.addBatch(sql);
		int[] a = st.executeBatch();
		for(int r:a){
			System.out.println(r);//r為每條sql語句所影響的記錄數
		}
	}

預處理

 

 

public void preparedBatch() throws Exception{
		Connection con = ConnFactory.getConn();
		String sql = "insert into book(name,price,pub) values(?,?,?)";
		PreparedStatement pst = con.prepareStatement(sql);
		for(int i=0;i<5;i++){
			pst.setString(1, "Java"+i);
			pst.setDouble(2, 55.85+i);
			pst.setString(3, "2016-12-10 07:07:08");
			pst.addBatch(); //pst的方式不能帶參數sql
		}
		//pst.executeBatch();
		int[] a = pst.executeBatch();
		for(int r:a){
			System.out.println(r);//r為每條sql語句所影響的記錄數
		}
	}

注意:預處理的方式不能帶參數sql,普通的需要

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