數據庫連接的實現與理解

一、傳統JDBC:

/**
	 * 釋放資源
	 * 
	 * @param rs
	 * @param st
	 * @param conn
	 */
	public static void free(ResultSet rs, Statement st, Connection conn) {
		try {
			if (rs != null)
				rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (st != null)
					st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				if (conn != null)
					try {
						conn.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
			}
		}
	}
	public static Connection getConn() {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
		String username = "scott";
		String password = "tiger";
		Connection conn = null;
		try {
			Class.forName(driver); // classLoader,加載對應驅動
			conn = (Connection) DriverManager.getConnection(url, username,
					password);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
	public static int insertAndDelete(String sql) {
		Connection conn = getConn();
		int i = 0;
		PreparedStatement pstmt = null;
		try {
			pstmt = (PreparedStatement) conn.prepareStatement(sql);
			i = pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				pstmt.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return i;
	}
	public static List queryForList(String sql) {
		System.out.println("queryForList=======" + sql);
		Connection conn = getConn();
		PreparedStatement pstmt = null;
		List<Map> list = new ArrayList();
		try {
			pstmt = (PreparedStatement) conn.prepareStatement(sql);
			ResultSet rs = pstmt.executeQuery();
			int col = rs.getMetaData().getColumnCount();// 記錄數
			while (rs.next()) {
				Map<String, Object> map = new HashMap();
				for (int i = 1; i <= col; i++) {
					map.put(rs.getMetaData().getColumnName(i),
							rs.getObject(i) == null ? "" : rs.getObject(i));
				}
				list.add(map);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				pstmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;
	}
    /**
        sql2 = "{call wzx_update_word()}";
    **/
	public static int doProcedure(String sql) {
		Connection conn = getConn();
		CallableStatement statement = null;
		try {
			statement = conn.prepareCall(sql);
			statement.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCTool.free(null, statement, conn);
		}
		return 0;
	}

傳統JDBC優缺點:

 優點:1.簡單,一個java類就可以開始操作數據庫。

            2. sql靈活,sql隨便寫,需要傳值就填問號即可。

            3.原始框架直接操作數據庫,效率高。

缺點: 1.安全性不高,SQL注入等。

            2.查詢體驗差(很難獲得bean,或List<bean>)。

            3.連接使用釋放難控制,萬一程序異常連接沒有釋放,造成數據庫內存泄漏,需要重啓數據庫。

            4.不適用大型應用,成千上萬個人申請連接,再斷開,會佔用系統資源,嚴重的會造成服務器崩潰。

二、連接池

      數據庫連接池負責分配、管理和釋放數據庫連接,它允許應用程序重複使用一個現有的數據庫連接,使用完再放回到連接池中,而不是重新建立一個。連接池在初始化時將創建一定數量的數據庫連接放到連接池中。

小提示:oracle數據庫最大連接數默認150,也就是最多創建150個connection。

知識擴展:connection實際上就是一個socket請求發送到數據庫進行通信。

爲什麼要使用連接池?

首先,沒有連接池的情況

1.如果程序出現異常,連接沒有釋放,造成數據庫內存泄漏,只能重啓數據庫。

2.幾百萬用戶請求,頻繁連接和釋放會消耗資源,導致服務器變慢。爲什麼會消耗資源?因爲創建連接時耗資源(比如進行分配內存的工作),大用戶數時就會影響網站響應速度。

3.和第1點類似,可以無限創建連接,導致數據庫內存泄漏。

使用連接池

連接池允許程序重複使用已有的connection,而不用重新創建。當有事務開始時,就從連接池中取一個可用的進行事務處理,沒有時則等待;事務處理完畢後再將連接放回連接池中

解決了什麼問題?

1.連接的釋放由連接池控制,不擔心內存泄漏。

2.connection重複利用,減少創建連接導致的資源消耗。

 如果併發超過連接池連接數,則鏈接排隊等待,直到空出鏈接。

如果併發遠遠大於一個數據庫的承受能力,怎麼辦?

       第一 , 可以 增加 緩存,減少查詢連接。
  第二, 可以部署數據庫集羣,讀寫分離。
  第三, 使用微服務,一個服務使用一個數據庫。
       第四,如果插入太多,也可以使用消息隊列,先把要插入的數據保存到隊列中,然後定時插入到數據庫。

 

 

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