我们在学习工作中可能经常使用Hibernate、Mybatis、jpa等框架。 这些框架很好地封装了数据库连接池,可能忽略了数据库的底层实现。 今天我们来看看如何手写简单的数据库连接池。 在此之前,让我们回想一下java连接数据库的步骤。
注册加载jdbc数据库驱动
第一,将驱动程序加载到内存中;第二。 自己在驱动程序管理器中注册当前加载的驱动程序。 驱动程序管理器是JDBC规范中唯一的Java类。
代码表示形式: class.forname(drivername ) /中DriverName=Driver包名称。 //Oracle的驱动程序名称=" Oracle.JDBC.driver.Oracle driver "。 //MySql的drivername=“com.MySQL.JDBC.driver”
得到连接对象 Connection
要连接到/*数据库,必须请求java.sql.DriverManager以获取表示与数据库的连接的Connection对象。 使用驱动程序管理器的getconnection(stringURL,String username,String password )方法指定的要连接的数据库的路径、数据库的用户名称和例如,连接到MySql数据库时,username和password都是root */string URL=' JDBC : MySQL 3360//localhost 33603306/test '; String username='root '; String password='root '; try { connection con=driver manager.getconnection (URL,username,password ); }catch(sqlexceptionse ) { System.out.println ('数据库连接失败!' ); se.printStackTrace (; (/*1、驱动程序管理器在JDBC规范中是类而不是接口。 一种服务类,用于管理JDBC驱动程序并提供getConnection ()方法以建立APP应用程序和数据库之间的连接。 JDBC驱动程序加载到内存后,自行注册到驱动程序管理器。 当此代码行发出连接请求时,驱动程序管理器类将使用注册的JDBC驱动程序创建与数据库的连接。 2、驱动程序管理器. getconnection ()是一种静态方法。 3、驱动程序管理器位于java.sql包中。 调用sql包中任何类(包括接口)的任何方法都会报告编译时异常SQLException。 在此,在一个try块之后使用多个catch块进行解决。 4、方法参数URL :统一资源定位符。 我们连接的数据库位于哪个主机上? 这由ip地址决定。 此主机上可能安装了一些数据库软件,如SqlServer、mysql和oracle。 那么,连接到哪个数据库由端口号决定。 端口编号也称为服务编号监听编号,其中sqlserver为1433,mysql为3306,oracle为1521: 下表列出了常用数据库软件的url表示形式。 Oracle : JDBC : Oracle : thin : @ IP :1521: dbname; MySQL:JDBC : MySQL ://IP :3306: dbname; SQL server:JDBC : SQL server ://IP :1443; databaseName=dbName; 5、使用本地ip地址连接时,需要关闭防火墙。 如果无法连接,则无需使用localhost或127.0.0.1关闭防火墙。 */
创建 Statement对象/*1,执行静态SQL语句。 通常在Statement实例中实现。 2、执行动态SQL语句。 通常在PreparedStatement实例中实现。 3、执行数据库存储过程。 通常在CallableStatement实例中实现。 //详细实现方法: sql注入statement stmt=con.create statement (); 可以防止//SQL向preparedstatementpstmt=con.preparestatement (SQL )注入; callablestatementcstmt=con.prepare call (' { calldemosp )? () );
书写sql语句并执行sql
/*Statement接口有三种方法:执行查询、执行更新和执行1、结果执行查询(字符串SQL )。 执行查询数据库的SQL语句。 返回结果集" ResultSet "对象
。 2、int executeUpdate(String sql):用于运行INSERT、UPDATE或DELETE语句以及SQL DDL语句,如:CREATETABLE和DROP TABLE等 3、execute(sql):用于运行返回多个结果集、多个更新计数或二者组合的 语句。*/ //详细实现的代码: ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ; int rows = stmt.executeUpdate("INSERTINTO ...") ; boolean flag =stmt.execute(String sql) ;
处理结果 两种情况:
关闭资源释放资源
客户端每访问一次数据库,数据库返回客户端数据,伴随的都是一次连接的创建和销毁。引入连接池主要的作用就是为了提高性能, 因为创建新的JDBC连接会导致联网操作和一定的JDBC驱动开销,其次才是减少资源开销。
当某一线程需要用JDBC在MySQL或其他数据库上执行操作时,需要用到由连接池提供的连接。使用连接完成线程后,线程会将连接返回给连接池,以便该连接能够被其他需要使用连接的线程使用。从连接池“借出”连接时,该连接仅供请求它的线程使用。从编程观点看,其效果等同于每次需要JDBC连接时调用DriverManager.getConnection(),但是,采用连接池技术,可通过使用新的或已有的连接结束线程。连接池技术能显著增加Java应用程序的性能,同时还能降低资源使用率。
市面上主流的连接池有c3p0、dbcp、druid、tomcat-jdbc、HikariCP(springboot2.0默认连接池)、proxool等...
下面来手写实现简易的数据库连接池:
连接池实际上就是一个容器,某一时刻可能有多个线程获取连接和释放连接,所以需要保证线程的安全性