摘要
本文主要介绍了JDBC的基本使用方法,并提供了完整的代码实现。首先介绍了JDBC的背景,然后给出了JDBC的基本操作代码实现,在其中加入详细的注解,解释其各步骤的目的与用意。最后解释了Druid连接池,以及相关的JDBC面试问题。
一、JDBC介绍
Java类型与数据库类型不一致而产生了冲突,所以需要一种连接器将两种数据类型进行转换,从而实现Java访问数据库的功能。数据库产品较多,若各个厂家实现连接器的架构不一致,从而导致开发者需要对代码进行重构,也导致了数据库与项目的强耦合性。
Sun公司为了简化、统一对数据库的操作,定义了一套java操作数据库的接口的规范,称之为JDBC(Java Database Connectivity)。各数据库产品公司,只需根据JDBC接口进行相关实现,开发者根据接口进行编程,从而降低了耦合性,只需要引入数据库对应的JDBC jar包即可。
二、JDBC的使用
package ft.test.jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
class App {
@Test
void test() {
Connection conn = null;
PreparedStatement preparedStatement = null;
try {
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC";
String userName = "root";
String password = "123456789";
Class clz = Class.forName(driver);
conn = DriverManager.getConnection(url, userName, password);
//要获得数据库table的每列字段信息,需要创建元数据对象DatabaseMetaData
DatabaseMetaData metaData = conn.getMetaData();
//获取名为students的table各列信息
ResultSet columnSet = metaData.getColumns(null, url, "students", "%");
//循环获取table的各列
while(columnSet.next()) {
//获取该列字段的类型信息
String type = columnSet.getString("TYPE_NAME");
System.out.printf("columnType = %s ",type);
//获取该列字段的名称
String name = columnSet.getString("COLUMN_NAME");
System.out.println("columnName = "+name);
}
System.out.println("###########################################");
String sql = "select * from students where age = ?";
//创建PreparedStatement对象
preparedStatement = conn.prepareStatement(sql);
//向sql语句中填充值
preparedStatement.setObject(1, 100);
//对数据库执行操作
ResultSet results = preparedStatement.executeQuery();
//循环遍历结果集中的每一列
while(results.next()) {
for(int i=0; i<results.getMetaData().getColumnCount(); i++) {
//获取每列字段的值
System.out.print(results.getObject(i+1)+" ");
}
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
//执行相应的关闭操作
try {
if(conn != null) {
conn.close();
}
if(preparedStatement != null) {
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
程序执行结构如下所示:
columnType = INT columnName = id
columnType = VARCHAR columnName = name
columnType = INT columnName = age
columnType = VARCHAR columnName = password
###########################################
1 feng 100 feng
三、连接池
3.1、连接池介绍
Java访问数据库时,一次数据库访问对应一个物理连接,每次访问数据库都需要为其打开物理连接,结束时为其关闭物理连接,在百万访问量时,这种数据库访问方式造成了巨大的系统开销,需要改进。
基于以上缺点,连接池提出了改进方式。系统运行时,提前创建足够的物理连接,这些物理连接称为连接池。当Java需要一个物理连接时,不需要创建新的物理连接而是从连接池中直接取,用完时不需要关闭物理连接,而是将其归还于连接池中。这样的策略大大降低了系统的开销。
3.2、Druid连接池的使用
Druid是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。需要下载Druid jar包并加入build path。
使用连接池的具体代码如下所示:
package ft.test.jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.jupiter.api.Test;
import com.alibaba.druid.pool.DruidDataSource;
class App {
@Test
void test() {
Connection conn = null;
PreparedStatement preparedStatement = null;
try {
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC";
String userName = "root";
String password = "123456789";
//使用连接Druid连接池
DruidDataSource druid=new DruidDataSource();
druid.setDriverClassName(driver);
druid.setUrl(url);
druid.setUsername(userName);
druid.setPassword(password);
conn = druid.getConnection();
//要获得数据库table的每列字段信息,需要创建元数据对象DatabaseMetaData
DatabaseMetaData metaData = conn.getMetaData();
//获取名为students的table各列信息
ResultSet columnSet = metaData.getColumns(null, url, "students", "%");
//循环获取table的各列
while(columnSet.next()) {
//获取该列字段的类型信息
String type = columnSet.getString("TYPE_NAME");
System.out.printf("columnType = %s ",type);
//获取该列字段的名称
String name = columnSet.getString("COLUMN_NAME");
System.out.println("columnName = "+name);
}
System.out.println("###########################################");
String sql = "select * from students where age = ?";
//创建PreparedStatement对象
preparedStatement = conn.prepareStatement(sql);
//向sql语句中填充值
preparedStatement.setObject(1, 100);
//对数据库执行操作
ResultSet results = preparedStatement.executeQuery();
//循环遍历结果集中的每一列
while(results.next()) {
for(int i=0; i<results.getMetaData().getColumnCount(); i++) {
//获取每列字段的值
System.out.print(results.getObject(i+1)+" ");
}
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
//执行相应的关闭操作
try {
if(conn != null) {
conn.close();
}
if(preparedStatement != null) {
preparedStatement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}