本篇内容包括:数据库连接池概述、JDBC 连接池原理、JDBC 连接池 Demo(addBatch demo、获取主键 demo、查看数据库的元数据 demo等)以及其他类型数据库连接池的介绍(比如 Druid)。
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。
连接池优点:
JDBC 连接池的基本原理:
commons-dbcp commons-dbcp 1.4
# 配置数据库的连接信息
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/databaseName
username=userName
password=password
public class DbUtils2 {private static String driver;private static String url;private static String username;private static String password;/*** 声明数据源,用于配置数据库的链接信息*/private static BasicDataSource dataSource;static {Properties prop = new Properties();InputStream ips = DbUtils2.class.getClassLoader().getResourceAsStream("jdbc.properties");try {//加载配置文件prop.load(ips);//获取我们在配置文件中配置的driver等信息driver = prop.getProperty("driver");url = prop.getProperty("url");username = prop.getProperty("username");password = prop.getProperty("password");//创建数据源dataSource = new BasicDataSource();//设置数据库的连接信息:dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);//设置初始连接数量dataSource.setInitialSize(3);//设置最大连接数量dataSource.setMaxActive(3);} catch (IOException e) {e.printStackTrace();} finally {try {//关闭资源ips.close();} catch (IOException e) {e.printStackTrace();}}}public static Connection getConn() throws Exception {// 从连接池中获取连接Connection conn = dataSource.getConnection();return conn;}public static void close(Connection conn, Statement stat, ResultSet rs) {try {if (rs != null) {rs.close();}} catch (SQLException e) {e.printStackTrace();}try {if (stat != null) {stat.close();}} catch (SQLException e) {e.printStackTrace();}try {if (conn != null) {//打开自动提交conn.setAutoCommit(true);conn.close();}} catch (SQLException e) {e.printStackTrace();}}
}
public static void main(String[] args) {Scanner scan = new Scanner(System.in);System.out.println("请输入用户名");String username = scan.nextLine();Scanner scr = new Scanner(System.in);System.out.println("请输入密码");String password = scr.nextLine();boolean b = login(username, password);if (b) {System.out.println("登陆成功");} else {System.out.println("登录失败");}}private static boolean login(String username, String password) {String sql = "select count(*) from table_user where username=? and password=?";Connection conn = null;PreparedStatement stat = null;ResultSet rs = null;try {conn = DbUtils2.getConn();stat = conn.prepareStatement(sql);stat.setString(1, username);stat.setString(2, password);rs = stat.executeQuery();while (rs.next()) {//得到查询的数量int count = rs.getInt(1);if (count > 0) {return true;}}} catch (Exception e) {e.printStackTrace();} finally {DbUtils2.close(conn, stat, rs);}return false;}
@Testpublic void testAddBatch01() {String sql1 = "insert into table_user values(null,'悟空','aaa')";String sql2 = "insert into table_user values(null,'八戒','bbb')";String sql3 = "insert into table_user values(null,'沙僧','ccc')";Connection conn = null;Statement stat = null;ResultSet rs = null;try {conn = DbUtils2.getConn();stat = conn.createStatement();stat.addBatch(sql1);stat.addBatch(sql2);stat.addBatch(sql3);//执行批量操作stat.executeBatch();} catch (Exception e) {e.printStackTrace();} finally {DbUtils2.close(conn, stat, rs);}}
@Testpublic void testAddBatch02() {String sql = "insert into table_user values(null,?,?)";Connection conn = null;PreparedStatement stat = null;ResultSet rs = null;try {conn = DbUtils2.getConn();stat = conn.prepareStatement(sql);stat.setString(1, "刘备");stat.setString(2, "aaa");//添加到批量处理stat.addBatch();stat.setString(1, "关羽");stat.setString(2, "bbb");stat.addBatch();stat.setString(1, "张飞");stat.setString(2, "ccc");stat.addBatch();stat.executeBatch();} catch (Exception e) {e.printStackTrace();} finally {DbUtils2.close(conn, stat, rs);}}
@Testpublic void testAddBatch03() {String sql = "insert into table_user values(null,?,?)";Connection conn = null;PreparedStatement stat = null;ResultSet rs = null;try {conn = DbUtils2.getConn();stat = conn.prepareStatement(sql);for (int i = 0; i < 100; i++) {stat.setString(1, "name" + i);stat.setString(2, "admin");stat.addBatch();//下面写法可以避免内存溢出if (i % 20 == 0) {stat.executeBatch();//清除批处理内容stat.clearBatch();}}stat.executeBatch();} catch (Exception e) {e.printStackTrace();} finally {DbUtils2.close(conn, stat, rs);}}
@Testpublic void testPrimaryKey() {Connection conn = null;Statement stat = null;ResultSet rs = null;try {conn = DbUtils2.getConn();stat = conn.createStatement();String sql = "insert into table_user values(null,'小明','abc')";//执行SQL并且制定需要获取自增主键值stat.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);//获取返回的主键值rs = stat.getGeneratedKeys();while (rs.next()) {int id = rs.getInt(1);System.out.println("自增主键" + id);}} catch (Exception e) {e.printStackTrace();} finally {DbUtils2.close(conn, stat, rs);}}
@Testpublic void testMetadata() {Connection conn = null;Statement stat = null;ResultSet rs = null;try {conn = DbUtils2.getConn();stat = conn.createStatement();//得到数据库的元数据DatabaseMetaData dbData = conn.getMetaData();System.out.println("驱动版本:" + dbData.getDriverMajorVersion());System.out.println("用户名:" + dbData.getUserName());System.out.println("链接地址:" + dbData.getURL());System.out.println("数据库名称:" + dbData.getDatabaseProductName());//获取表相关的元数据rs = stat.executeQuery("select * from table_user");ResultSetMetaData rsData = rs.getMetaData();//得到表字段的数量int count = rsData.getColumnCount();for (int i = 0; i < count; i++) {String name = rsData.getColumnName(i + 1);String type = rsData.getColumnTypeName(i + 1);System.out.println(name + ":" + type);}} catch (Exception e) {e.printStackTrace();} finally {DbUtils2.close(conn, stat, rs);}}
在 Java 程序中,开源的数据库连接池有以下几种 :
javax.sql.XADataSource
并提供了连接池工具这些池底层都是对 driver-class-name=com.mysql.jdbc.Driver 对这个驱动进行了封装