十、JDBC--数据连接层(JDBC连接池)(十一)

一、JDBC连接

1.1 连接过程

		
	连接过程:
			1.加载驱动、获取连接对象
			2.执行sql
			3.关闭连接资源。
			

1.2 连接分析

1.2.1 频繁操作数据库出现的问题(连接池出现的原因)

在这里插入图片描述

	缺点:
		1.在JDBC中,连接资源是十分宝贵的,mysql仅仅支持几百个连接资源。
		2.连接对象的创建和销毁也是十分消耗系统资源。
		3.如果频繁的操作数据库,则连接对象也需要频繁的被打开和关闭,严重
		  消耗系统资源。
		  
		假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪
		费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。
		
		所以在此情景下,我们引入了连接池技术。

1.2.2 连接的优化

在这里插入图片描述

	 预先创建一组连接,有的时候每次取出一个; 用完后,放回;
1.2.3 连接池的一般参数
	驱动名、用户名、密码、初始化连接数、最大连接数、最大空闲时间。

二、连接池

2.1 JDBC1.0 与 JDBC2.0区别


    JDBC1.0原来是用DriverManager类产生一个对数据源的连接,
	JDBC2.0用一种替代的方法,使用DataSource的实现,代码变得更小巧精灵,也更容易控制。

	DataSource接口是更好的连接数据源的方法。
						

2.2 连接池技术的引入

				
		连接池出现的原因:
						创建连接和销毁连接是十分消耗内存资源的,
						如果用户频繁操作数据库,则会影响程序的执行效率。


		
		连接池的作用:
						管理连接资源,提高效率
	
		

2.3 连接池技术的实现

	
	数据源技术包含了连接池技术的实现:
			1.现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce
			  的实现,即数据源的实现。有一些开源组织提供了数据源的独立实现:
		
			2.Sun公司规定,如果是连接池技术,则用户需要实现DataSource接口(javax.sql.DataSource)。
			  数据源技术包含了连接池技术的实现。		
	
	连接池技术(数据源技术):			
			1.自定义连接池
			2.使用第三方连接池	
						DBCP 数据库连接池  (tomcat)
						C3P0 数据库连接池   (hibernate)
														
			3.使用服务器自带的连接池
			

三、自定义连接池

public class MyPool {
	
	//默认连接数
	private int init_num=3;
	
	//最大连接数
	private int max_num=4;
	
	//当前连接数
	private int current_num=3;
	
	//连接池
	private LinkedList<Connection>  pool=new LinkedList<Connection>();
	
	/**
	 * 初始化连接池
	 */
	public MyPool() {
		for(int i=0;i<init_num;i++) {
			pool.addLast(createCon());
		}
	}
	
	
	/**
	 * 创建连接对象
	 * 
	 * @return
	 */
	@Test
	public Connection createCon() {
		
		try {
			
			Class.forName("com.mysql.jdbc.Driver");
			Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
			
			
			/**	创建代理类	**/
			Connection proxy=(Connection)Proxy.newProxyInstance(Connection.class.getClassLoader(),new Class[] {Connection.class}, new InvocationHandler() {
				
				@Override
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					
					String methodName = method.getName();
					if("close".equals(methodName)) {
						System.out.println("调用了close方法");
						
						//当用户调用close方法时,记录连接数也要发生改变
						current_num--; //记录当前连接数
						Object result = method.invoke(conn, args);
						return result;
					}
					
					return method.invoke(conn, args);
				}
			});
			
			return proxy;

			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	
		return null;
	}
	
	
	

	
	/**
	 * 获取连接
	 * 
	 * @return
	 */
	public Connection getConn() {
		
		//1.如果连接池中有连接对象,则从连接池中获取
		if(pool.size()>0) {
			return pool.removeFirst();
		}
		
		//2.当连接池中没有连接对象,则需判断当前连接数是否大于最大连接数
		if(current_num < max_num) {
			current_num++; //记录当前连接数
			return createCon();
		}
		
		throw new RuntimeException("已达到最大连接数...");
		
	}
	
	
	/**
	 * 释放连接
	 * 
	 * @param conn
	 */
	public void releaseConn(Connection conn) {
		
		
		//当连接池中连接数小于初始化连接数
		if(pool.size()<3) {
			pool.addLast(conn);
		}  
		
		//当连接池中连接数大于初始化连接数
		try {
			conn.close();
			current_num--;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
	public static void main(String[] args) throws SQLException {
		MyPool pool=new MyPool();
		Connection conn = pool.getConn();
		Connection conn2 = pool.getConn();
		Connection conn3 = pool.getConn();
		
		Connection conn4= pool.getConn();
		conn4.close(); //该方法触发了current_num--
		

		System.out.println(pool.current_num);
	}
	
}

四、DBCP连接池

4.1 使用DBCP连接池的引入的jar包

	
	DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序
	应在系统中增加如下两个 jar 文件:
	
				•Commons-dbcp.jar:连接池的实现
				•Commons-pool.jar:连接池实现的依赖库

4.2 使用DBCP连接池

		
		核心类:BasicDataSource
			   		
			   	硬编码方式:
							BasicDataSource dataSouce = new BasicDataSource();
							dataSouce.setUrl("jdbc:mysql:///jdbc_demo");			//数据库连接字符串
							dataSouce.setDriverClassName("com.mysql.jdbc.Driver");  
				
				配置方式:
							DataSource dataSouce = BasicDataSourceFactory.createDataSource(Demo.class.getResourceAsStream("/db.properties"));
							
							db.properties
											url=jdbc:mysql:///jdbc_demo
											driverClassName=com.mysql.jdbc.Driver
											username=root
											password=root
											initialSize=3
											maxActive=6
											maxIdle=3000
						
4.2.1 硬编码方式使用DBCP连接池

public class App_DBCP {

	// 1. 硬编码方式实现连接池
	@Test
	public void testDbcp() throws Exception {
		// DBCP连接池核心类
		BasicDataSource dataSouce = new BasicDataSource();
		
		// 连接池参数配置:初始化连接数、最大连接数 / 连接字符串、驱动、用户、密码
		dataSouce.setUrl("jdbc:mysql:///jdbc_demo");			//数据库连接字符串
		dataSouce.setDriverClassName("com.mysql.jdbc.Driver");  //数据库驱动
		dataSouce.setUsername("root");							//数据库连接用户
		dataSouce.setPassword("root"); 							//数据库连接密码
		dataSouce.setInitialSize(3);  // 初始化连接
		dataSouce.setMaxActive(6);	  // 最大连接
		dataSouce.setMaxIdle(3000);   // 最大空闲时间
		
		// 获取连接
		Connection con = dataSouce.getConnection();
		con.prepareStatement("delete from admin where id=3").executeUpdate();
		// 关闭
		con.close();
	}
	

4.2.2 配置方式使用DBCP连接池

db.properties


	url=jdbc:mysql:///jdbc_demo
	driverClassName=com.mysql.jdbc.Driver
	username=root
	password=root
	initialSize=3
	maxActive=6
	maxIdle=3000
	
[配置方式实现DBCP连接池,  配置文件中的key与BaseDataSouce中的属性一样]

	@Test
	// 2. 【推荐】配置方式实现连接池  ,  便于维护
	public void testProp() throws Exception {
		// 加载prop配置文件
		Properties prop = new Properties();
		// 获取文件流
		InputStream inStream = App_DBCP.class.getResourceAsStream("db.properties");
		// 加载属性配置文件
		prop.load(inStream);
		// 根据prop配置,直接创建数据源对象
		DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);
		
		// 获取连接
		Connection con = dataSouce.getConnection();
		con.prepareStatement("delete from admin where id=4").executeUpdate();
		// 关闭
		con.close();
	}
}

五、C3P0连接池

5.1 使用C3P0连接池的引入的jar包

	
	C3P0连接池:
		最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!
		
		使用C3P0连接池需要导包:
					c3p0-0.9.1.2.jar

5.2 使用C3P0连接池

		
		核心类:CombopooledDataSource 
			   		
			   	硬编码方式:
						ComboPooledDataSource dataSource = new ComboPooledDataSource();

						dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo");
						dataSource.setDriverClass("com.mysql.jdbc.Driver");

				XML配置方式: 
						自动加载src下c3p0的配置文件【c3p0-config.xml】
				
						//1.使用默认数据配置进行连接
						ComboPooledDataSource dataSource = new ComboPooledDataSource();
						
						//2.指定数据配置进行连接
						ComboPooledDataSource dataSource = new ComboPooledDataSource("name");
						
5.2.1 硬编码方式使用C3P0连接池

	@Test
	//1. 硬编码方式,使用C3P0连接池管理连接
	public void testCode() throws Exception {
		
		// 创建连接池核心工具类
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		
		// 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数、最大空闲时间
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo");
		dataSource.setDriverClass("com.mysql.jdbc.Driver");
		dataSource.setUser("root");
		dataSource.setPassword("root");
		dataSource.setInitialPoolSize(3);
		dataSource.setMaxPoolSize(6);
		dataSource.setMaxIdleTime(1000);
		
		// ---> 从连接池对象中,获取连接对象
		Connection con = dataSource.getConnection();
		// 执行更新
		con.prepareStatement("delete from admin where id=7").executeUpdate();
		// 关闭
		con.close();
	}
	
5.2.2 XML配置方式使用C3P0连接池
	C3P0连接池会自动加载src目录下的c3p0-config.xml配置文件。
	
	C3P0连接池的XML可以配置多个数据源。

c3p0-config.xml
放在classpath的根目录下。

<c3p0-config>
	
	<!-- 默认数据库  -->
	<default-config>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/day11</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">root</property>
		<property name="initialPoolSize">3</property>
		<property name="maxPoolSize">6</property>
		<property name="maxIdleTime">1000</property>
	</default-config>

	<!-- 可以配置多数据源 -->
	<named-config name="db33">
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">root</property>
		<property name="initialPoolSize">3</property>
		<property name="maxPoolSize">6</property>
		<property name="maxIdleTime">1000</property>
	</named-config>
	
	

</c3p0-config>

使用


	//1. XML配置方式,使用C3P0连接池管理连接
	//读取默认数据库配置进行连接
	public void testXML() throws Exception {

		// 自动加载src下c3p0的配置文件【c3p0-config.xml】
		ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置
		
		// 获取连接
		Connection con = dataSource.getConnection();
		// 执行更新
		con.prepareStatement("delete from admin where id=5").executeUpdate();
		// 关闭
		con.close();	
	}

	//读取指定数据库配置进行连接
	public void testXML() throws Exception {

		ComboPooledDataSource dataSource = new ComboPooledDataSource("db33");// 使用默认的配置
		
		Connection con = dataSource.getConnection();
		con.prepareStatement("delete from admin where id=5").executeUpdate();
		con.close();	
	}
	
	
发布了94 篇原创文章 · 获赞 0 · 访问量 619

猜你喜欢

转载自blog.csdn.net/weixin_45602227/article/details/104351248
今日推荐