java自學之路-----jdbc_基礎

JDBC(Java Data Base Connectivity):便於應用程序通過jdbc來操作數據庫的數據

操作數據庫基本步驟:(先導入該數據庫的驅動程序){

1.先與數據庫進行連接,獲取該數據庫的對象(1.先加載數據庫的驅動 2.通過數據庫的基本信息來獲取連接 3.通過連接獲取操作數據庫的statement對象)

2.然後使用該對象執行sql語句{

數據庫url:用於標識數據庫的位置,程序需要通過url告訴jdbc程序連接那個數據庫,寫法:

jdbc : mysql : // localhost:3306 / mydb ?參數名:參數值

協議 子協議       主機:端口          數據庫名

		String url = "jdbc://localhost:3306/mydb";//數據庫的地址
		String user = "root";//數據庫用戶名
		String password = "root";//數據庫密碼
//第一種方式:
//		1.先加載驅動
		DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//		2.通過驅動獲取連接
		Connection conn1 = DriverManager.getConnection(url, user, password);
//		3.通過連接獲取statement對象
		Statement st1 = conn1.createStatement();
//	缺點:1.驅動程序註冊兩次:通過查看驅動類driver.class可以知道,該類有一個構造函數,在加載該類的時候自動在驅動裏註冊一次,所以在內存中就會出現兩個driver對象
//		  2.程序import了mysql驅動,導致程序依賴mysql驅動api,離開了該jar包,程序編譯就通不過
//第二種方式:
//		1.先加載驅動
		Class.forName("com.mysql.jdbc.Driver");
//		2.通過驅動獲取連接
		Connection conn2 = DriverManager.getConnection(url, user, password);
//		3.通過連接獲取statement對象
		Statement st2 = conn2.createStatement();
//	優點:該方式不會導致驅動對象在內存中重複出現,並且該方式下,程序只用一個字符串,不需要依賴具體驅動。	

Connection:代表數據庫的連接,用於客戶端與數據庫的交互

1.createStatement();創建向數據庫發送sql的statement對象

2.prepareStatement(sql);創建向數據庫發送預編譯sql的preparestatement對象

3.prepareCall(sql);創建執行存儲過程的callableStatement對象

4.setAutoCommit(boolean b);設置事務是否自動提交

5.commit();在連接上提交事務

6.rollback();在此鏈接上回滾事務

Statement:用於向數據庫發送sql語句

1.executeQuery(sql);用於向數據庫發送查詢語句。返回resultset對象

2.executeUpdate(sql);用於向數據庫發送更新,插入,刪除語句。返回影響數據的行數,大於0說明執行成功

3.execute(sql);用於向數據庫發送任意語句。返回是否執行成功

4.addBatch(sql);將多條sql語句放在一個批處理中

5.executeBatch();向數據庫發送一批sql語句

}

3.如果是select的sql就會返回結果集:ResultSet

4.通過該結果集可以獲取select的所有數據{

//	如果sql爲select
//		4.通過對象執行sql語句
//		5.獲取ResultSet對象
//		6.遍歷結果集,獲取數據
		ResultSet rs = st.executeQuery("select * from users");//select的sql
//		int num = st.executeUpdate("update users set name='a'");
		while(rs.next()){
			Object value1 = rs.getObject(1);
			String value2 = rs.getString(2);
			Int value3 = rs.getInt(3);
//			...通過列的名字或者該列所的索引作爲參數來獲取該列的值
		}

ResultSet:用於代表sql語句的執行結果,該對象採用類似表格的方式來封裝執行結果。它維護了一個指向表格數據行的遊標,初始的時候,遊標在第一行之前,調用next()方法,遊標就指向了具體的數據行,再通過get方法獲取該行數據。

獲取任意類型的數據

getObject(int index);

getObject(String columnName);

獲取相對應該列的屬性的方法

}

5.釋放資源{

		} finally{
			if(rs!=null){
				try {
					rs.close();
				} catch (Exception e) {
					rs = null;
				}
			}
			if(st!=null){
				try {
					st.close();
				} catch (Exception e) {
					st = null;
				}
			}if(conn!=null){
				try {
					conn.close();
				} catch (Exception e) {
					conn = null;
				}
			}
		}

1.jdbc程序運行結束之後,需要釋放程序在運行過程中創建的那些與數據庫進行交互的對象,通常 是ResultSet,Statement,和Connection對象

2.Connection對象,這是非常稀有的資源,用完後必須馬上釋放,如果Connection不能及時、正確的關閉,極易導致系統宕機。所以需要儘量晚創建,儘量早的關閉

3.爲保證釋放程序的代碼執行,就必須放在finally語句中

}

}

創建工具類,簡化操作{

public class JdbcUtils {
//	存儲配置信息
	private static Properties config = new Properties();
//	提供一個靜態代碼塊,確保第一次加載該類的時候將相關信息,加載到內存中
	static{
		try {
//		從配置文件中獲取數據庫相關信息,加載到config中,該文件要放在類路徑下
			InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
			config.load(in);
			Class.forName(config.getProperty("driver"));
		} catch (Exception e) {
//			直接報錯,因爲配置文件有問題,連接不了數據庫
			throw new ExceptionInInitializerError(e);
		}
	}
	
//	提供一個靜態方法,爲程序提供連接,異常直接拋給調用程序處理
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(config.getProperty("url"), config.getProperty("user"), config.getProperty("password"));
	}
//	提供一個釋放資源的方法
	public static void release(Connection conn, Statement st, ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (Exception e) {
//				記錄下異常信息
				e.printStackTrace();
				rs = null;
			}
		}
		if(st!=null){
			try {
				st.close();
			} catch (Exception e) {
				e.printStackTrace();
				st = null;
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();
				conn = null;
			}
		}
	}
}

db.properties文件{

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/mydb

user=root

password=root

}


工廠類:將程序與dao層的操作進行解耦,{

//在web程序中,該工廠實現了service和dao層解耦。在修改底層代碼的時候,不需要修改上層的代碼,只需要修改配置文件即可
public class DaoFactory {
//	讀取配置文件來創建接口對應的dao實例,也可以將該代碼放在構造函數中
	private static Properties prop = new Properties();
	static{
		try {
//			dao.properties文件內 包含: UserDao = cn.halm.dao.UserDaoImpl
			prop.load(DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties"));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
//需要設計爲單例模式
//	1.構造函數私有化
	private DaoFactory() {}
//	2.創建該類的一個私有的實例化對象
	private static DaoFactory instance = new DaoFactory();
//	3.將該對象提供給程序
	public static DaoFactory getInstance(){
		return instance;
	}
//	提供一個方法,從配置文件中讀取信息後根據接口創建相應的實現類實例
	public <T> T createDao(Class interfaceClazz){
		try {
//		通過接口字節碼文件獲取接口名
			String interfaceName = interfaceClazz.getSimpleName();
//		通過接口名獲取配置文件中對應的該接口的實現類的名稱
			String implName = prop.getProperty(interfaceName);
//		返回該實現類的實例
			return (T) Class.forName(implName).newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

}

PreparedStatement對象{

1.是Statement的子類

2.可以有效的防止SQL注入:

sql = "select * from users where username = '"+username+"' and password = '"+password+"'";如果兩個變量password,username="'or 1=1 or username='",那麼該語句就爲:select * from users where username='' or true or username=''——>select * from users where true;該語句就一定能從數據庫中找到數據。這就是SQL注入!如果使用PreparedStatement會對傳入的變量進行轉義,就能預防該問題

3.該對象會對sql語句進行預編譯,以減輕數據庫服務器的壓力,提高效率。statement對象會使數據庫頻繁編譯sql,可能造成數據庫緩衝區溢出

4.允許使用佔位符替換參數,簡化sql語句的編寫

用法:

//			定義sql語句,包含佔位符“?”
			String sql = "select * from users where username=? and id=?";
//			預編譯sql語句獲取對象
			PreparedStatement st = conn1.prepareStatement(sql);
//			從1開始,不同類型的數據使用不同的方法
			st.setString(1, user.getUsername());
			st.setInt(2, user.getId());
			st.executeQuery();
//			st.executeUpdate();insert,update,delete語句使用


獲取插入數據的主鍵值:getGeneratedKeys()獲取新插入數據的在數據庫中自動增長的值,一般爲主鍵{

如果沒有這個方法,如果該主鍵值在數據庫中被設置爲自動增長,插入數據就不需要傳入主鍵值,所以就無法直接獲取該主鍵值,必須通過查表

注意:在mysql數據庫中只能有一個字段修飾爲auto_increment

//			獲取執行執行sql語句的對象,指定一個常量值Statement.RETURN_GENERATED_KEYS,說明該自動增長的主鍵值被返回,如果不是insert的sql可以忽略該參數值,沒有該參數,就不返回主鍵值
			PreparedStatement st = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
//			使用該方法獲取新生成的包含在數據庫中自動增長的值的ResultSet對象
//			該對象中只有一列,存放新生成的主鍵值,不是insert的sql語句,該方法無用
			ResultSet rs = st.getGeneratedKeys();
//			遍歷,獲取值
			rs.next();
			rs.getInt(1);

}
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章