数据库连接池以及一个Java中的JDBC流程
远程连接数据库采用 Tcp 协议,
一个 web 服务器,一个客户端,客户端发出查询到网页的时候,web 服务器就会去数据库进行查询。会去找 mysqld 进程。这种模型只能通过 tcp/ip 协议来实现。
还有一种情况就是 web 服务 mysql 在同一台服务器上,这种场景可以避免使用 tcp/ip 的网络,使用 tcp/ip 可能会受到黑客的攻击,那么这种只能通过客户端对自己的某个嵌套字进行衔接,以本地文件进行衔接。用户通过 tcp/ip 协议链接到服务器,对端口进行攻击,但是链接不进来,因为没有 tcp/ip 的端口的一个开放,只采用文件方式进行访问。
控制台通过:
mysql -u root -p
定义:JDBC(Java DataBase Connectivity,java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。JDBC 提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
public class JDBCTest { //这是驱动名称,此例子中我们加载的是 mysql 的驱动,在之前需要导入 mysql 的驱动 jar 包 public static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; //连接数据库的 url,各个数据库厂商不一样,此处为 mysql 的; 后面是创建的数据库名称 public static final String JDBC_URL = "jdbc:mysql://localhost:3306/jdbc_test"; //连接数据库所需账户名 public static final String JDBC_USERNAME = "root"; //用户名对应的密码,我的 mysql 密码是 123456 public static final String JDBC_PASSWORD = "123456"; @Test public void testUpdate() { Connection connection = null; PreparedStatement preparedStatement = null;</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一步:加载Driver类,注册数据库驱动</span>
Class.forName(JDBC_DRIVER);
//第二步:通过 DriverManager, 使用 url,用户名和密码建立连接 (Connection)
connection = DriverManager.getConnection(JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD);
//第三步:通过 Connection,使用 sql 语句打开 Statement 对象;
preparedStatement = connection.prepareStatement("UPDATE student SET age=20 WHERE name=?");
//传入参数,之所以这样是为了防止 sql 注入
preparedStatement.setString(1, "xiaoming");
//第四步:执行语句,将结果返回 resultSet
int count = preparedStatement.executeUpdate();
//第五步:对结果进行处理
System.out.println(count);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//第六步:倒叙释放资源 resultSet-》preparedStatement-》connection
try {
if (preparedStatement != null &&
!preparedStatement.isClosed()) {
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connection != <span style="color: rgba(0, 0, 255, 1)">null</span> &&<span style="color: rgba(0, 0, 0, 1)"> connection.isClosed()) { connection.close(); } } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) { e.printStackTrace(); } } }
}
jdbc 操作步骤总结如下:
1、 加载数据库驱动
2、 创建并获取数据库链接
3、 创建 jdbc statement 对象
4、 设置 sql 语句
5、 设置 sql 语句中的参数 (使用 preparedStatement)
6、 通过 statement 执行 sql 并获取结果
7、 对 sql 执行结果进行解析处理
8、 释放资源 (resultSet、preparedstatement、connection)
jdbc 问题总结如下:
1、 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
2、 Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
3、 向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数一一对应。
4、 对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。
由此引伸到了 Mybatis 框架
Statement 和 PrepareStatement 之间的区别
关系:PreparedStatement 继承自 Statement, 都是接口
区别:PreparedStatement 可以使用占位符,是预编译的,批处理比 Statement 效率高
1、PreparedStatement:表示预编译的 SQL 语句的对象。
接口:public interface PreparedStatement extends Statement 之间的继承关系
SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。
注:用于设置 IN 参数值的设置方法(setShort、setString 等等)必须指定与输入参数的已定义 SQL 类型兼容的类型。例如,如果 IN 参数具有 SQL 类型 INTEGER,那么应该使用 setInt 方法,问号的位置也是应该注意的,因为第一个问好的位置为 1,第二个问号的位置为 2
2、Statement: 用于执行静态 SQL 语句并返回它所生成结果的对象。
接口:public interface Statement extends Wrapper
在默认情况下,同一时间每个 Statement 对象只能打开一个 ResultSet 对象。因此,如果读取一个 ResultSet 对象与另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的当前 ResultSet 对象,则 Statement 接口中的所有执行方法都会隐式关闭它。
如以下操作:创建 statement 对象
Statement stat=conn.createStatement();
String sql="insert into lover values(6,'suxingxing',to_date('21-9-2016','dd-mm-yyyy'))";
stat.execute(sql);// 这里提交时应该有 sql 语句,不同于 PreparedStatment
数据库连接池:
数据库连接池原理:
数据库连接池的基本思想就是为数据库连接 建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定 连接池最大连接数来防止系统无尽的与数据库连接。
连接池技术尽可能多地重用了消耗内存地资源,大大节省了内存,提高了服务器地服务效率,能够支持更多的客户服务。通过使用连接池,将大大提高程序运行效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。 (简单来说就是不用频繁建立 Connection 连接然后销毁,可以重复利用这些 Connection 资源)
对于连接池中的事务管理:
在 Java 语言中,Connection 类本身提供了对事务的支持,可以通过设置 Connection 的 AutoCommit 属性为 false, 然后显式的调用 commit 或 rollback 方法来实现。但要高效的进行 Connection 复用,就必须提供相应的事务支持机制。可采用 每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。
连接池中的一个具体操作流程:
连接池的操作: (1)建立数据库连接池对象(服务器启动)。 (2)按照事先指定的参数创建初始数量的数据库连接(即:空闲连接数)。 (3)对于一个数据库访问请求,直接从连接池中得到一个连接。如果数据库连接池对象中没有空闲的连接,且连接数没有达到最大(即:最大活跃连接数),创建一个新的数据库连接。 (4)存取数据库。 (5)关闭数据库,释放所有数据库连接(此时的关闭数据库连接,并非真正关闭,而是将其放入空闲队列中。如实际空闲连接数大于初始空闲连接数则释放连接)。 (6)释放数据库连接池对象(服务器停止、维护期间,释放数据库连接池对象,并释放所有连接)。