数据库连接的实现与理解

一、传统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重复利用,减少创建连接导致的资源消耗。

 如果并发超过连接池连接数,则链接排队等待,直到空出链接。

如果并发远远大于一个数据库的承受能力,怎么办?

       第一 , 可以 增加 缓存,减少查询连接。
  第二, 可以部署数据库集群,读写分离。
  第三, 使用微服务,一个服务使用一个数据库。
       第四,如果插入太多,也可以使用消息队列,先把要插入的数据保存到队列中,然后定时插入到数据库。

 

 

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