概述
JDBC全称为Java DataBase Connectivity,翻译为Java数据库连接技术,是在服务端操作的一种技术。不受限于数据库的类型(多态思想),是一套通用的SQL数据库存取和操组的公共接口,定义了一套标准,为访问不同的数据库提供了统一途径。
使用步骤
(1)加载JDBC驱动,Java和数据通信的桥梁材料。
(2)获取Connection,Java程序和数据库的一次连接,搭建桥梁。
(3)创建Statement对象,由Connection产生,执行SQL语句,桥梁上的运输车。
(4)如果需要接收返回值,创建ResultSet对象,保存Statement执行之后查询到的结果。保存小车货物的仓库。
public class Test {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/test?userUnicode=true&characterEncoding=UTF-8";
String username = "root";
String password = "x5";
// String sql = "insert into student(name, age, sex) values('刘华强' ,35 ,'男')";
String sql = "select * from student";
try {
// 加载驱动,通过反射机制,获取运行时类
Class.forName("com.mysql.jdbc.Driver");
// 获取Connection连接
Connection connection = DriverManager.getConnection(url, username, password);
// 创建Statement命令
Statement statement = connection.createStatement();
// 通过ResultSet对象接收查询结果集
ResultSet resultSet = statement.executeQuery(sql);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
PreparedStatement
Statement的子类,提供了SQL占位符的功能。
存在意义:
(1)减少sql命令的字符串拼接操作,减少单双引号导致的错误。
(2)降低SQL注入的风险。
public class Test {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/test?userUnicode=true&characterEncoding=UTF-8";
String username = "root";
String password = "x5";
// String sql = "insert into student(name, age, sex) values('刘华强' ,35 ,'男')";
String sql = "select * from student where id = ?";
Integer id = 24;
try {
// 加载驱动,通过反射机制,获取运行时类
Class.forName("com.mysql.jdbc.Driver");
// 获取Connection连接
Connection connection = DriverManager.getConnection(url, username, password);
// 创建PreparStatement命令
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 设置占位符数值
preparedStatement.setInt(1, id);
// 通过ResultSet对象接收查询结果集
ResultSet resultSet = preparedStatement.executeQuery();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
JDBCTool
将加载数据库驱动,建立数据库连接等重复率高的代码封装成一个工具类,提升代码复用率。封装了JDBC使用四步骤中第一步、第二步(加载驱动的操作,创建数据库连接的操作)。
public class JDBCTool{
private static Connection connection;
private static String url = "jdbc:mysql://localhost:3306/test?useUnicode&characterEncoding=UTF-8";
private static String username = "root";
private static String password = "x5";
// 获取数据库连接
public static Connection getConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, username ,password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
// 关闭结果集、预编译语句、数据库连接
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if(statement != null) {
statement.close();
}
if(connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
使用时
Connection connection = JDBCTool.getConnection();
JDBCTool.close(resultSet, statement, connection);
数据库连接池(C3P0)
1 概述
为什么出现?
通过JDBC对数据库数据操作,每次都得用DriverManager创建Connection,验证账户密码等,使用完还得关闭连接,这些过程需要耗费大量资源,所以开始有人考虑复用数据库连接资源,于是出现了数据库连接池。
数据库连接池思想就是为数据库建立一个缓冲池,向缓冲池中投入一定数量的Connection对象,当需要获取数据库连接的时候,就从池中取出对象,用完再放回缓冲池中。
JDBC的数据库连接池,使用javax.sql.DataSource接口来完成,DataSource是官方提供的接口,使用的时候开发者不需要自己自己来实现,可以使用第三方的工具,如C3P0。
下载地址:https://sourceforge.net/projects/c3p0/
2 普通使用
(1)导入c3p0.jar
和mchange-commons-java.jar
包,引入工程。
(2)编写连接池代码(此处编写工具类为例)。
public class JDBCTool {
private static ComboPooledDataSource comboPooledDataSource;
private static String url = "jdbc:mysql://localhost:3306/test?useUnicode&characterEncoding=UTF-8";
private static String username = "root";
private static String password = "x5";
private static Connection connection;
static {
try {
// 创建数据库连接池
comboPooledDataSource = new ComboPooledDataSource();
// 加载数据库驱动
comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
// 配置数据库地址
comboPooledDataSource.setJdbcUrl(url);
// 配置数据库用户名
comboPooledDataSource.setUser(username);
// 配置数据库密码
comboPooledDataSource.setPassword(password);
// 配置初始化时数据库缓冲池中的连接数目
comboPooledDataSource.setInitialPoolSize(10);
// 配置运行时提供的连接最大数目
comboPooledDataSource.setMaxPoolSize(20);
// 配置运行时提供的空闲连接最小数目,当不够时触发申请新连接
comboPooledDataSource.setMinPoolSize(1);
// 每次申请新连接的数量
comboPooledDataSource.setAcquireIncrement(5);
// 配置连接超时时间
comboPooledDataSource.setCheckoutTimeout(3000);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
}
// 从连接池取连接
public static Connection getConnection() {
try {
connection = comboPooledDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
// 关闭ResultSet结果集、Statement语句、向连接池“归还”连接(Connection)
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if(resultSet != null) {
resultSet.close();
}
if(statement != null) {
statement.close();
}
if(connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3 XML使用
我们还可以简化,用xml文件形式配置数据库连接池信息,使用xml形式解析工程可以动态修改配置信息,不需要停止服务。
注意:
(1)xml文件名必须叫:c3p0-config.xml,不然无法识别
;
(2)初始化ComboPooledDataSource时,传入的参数必须是c3p0-config.xml中的<named-config>的name属性值
;
(3)存放在src目录下即可
。
文件内容如下:
<c3p0-config>
<!--使用默认的配置读取数据库连接池对象 -->
<default-config>
<!-- 连接参数 -->
<!--配置数据库驱动-->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!--配置数据库地址-->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8</property>
<!--配置数据库用户名-->
<property name="user">root</property>
<!--配置数据库密码-->
<property name="password">x5</property>
<!-- 连接池参数 -->
<!--配置初始化时数据库缓冲池中的连接数目-->
<property name="initialPoolSize">10</property>
<!--配置运行时提供的连接最大数目-->
<property name="maxPoolSize">20</property>
<!--配置运行时提供的空闲连接最小数目,当不够时触发申请新连接-->
<property name="minPoolSize">1</property>
<!--配置每次申请新连接的数量-->
<property name="acquireIncrement">5</property>
<!--配置连接超时时间-->
<property name="checkoutTimeout">3000</property>
</default-config>
<!--配置的名字-->
<named-config name="c3p0_config1">
<!-- 连接参数 -->
<!--配置数据库驱动-->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!--配置数据库地址-->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8</property>
<!--配置数据库用户名-->
<property name="user">root</property>
<!--配置数据库密码-->
<property name="password">x5</property>
<!-- 连接池参数 -->
<!--配置初始化时数据库缓冲池中的连接数目-->
<property name="initialPoolSize">10</property>
<!--配置运行时提供的连接最大数目-->
<property name="maxPoolSize">20</property>
<!--配置运行时提供的空闲连接最小数目,当不够时触发申请新连接-->
<property name="minPoolSize">1</property>
<!--配置每次申请新连接的数量-->
<property name="acquireIncrement">5</property>
<!--配置连接超时时间-->
<property name="checkoutTimeout">3000</property>
</named-config>
</c3p0-config>
改良版JDBCTool:
public class JDBCTool {
// 在此处输入xml文件中的配置名即可
private static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("c3p0_config1");
private static Connection connection;
// 从连接池取连接
public static Connection getConnection() {
try {
connection = comboPooledDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
// 关闭ResultSet结果集、Statement语句、向连接池“归还”连接(Connection)
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if(resultSet != null) {
resultSet.close();
}
if(statement != null) {
statement.close();
}
if(connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
DBUtil
1 概述
可以帮助开发者完成数据的封装(结果集 映射 Java对象)。
需要导入commons-dbutils.jar
到工程中,下载网址https://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi。
DBUtil中有一个重要的接口ResultHandler
:
ResultHandler 接口是用来处理结果集的,可以将查询到的结果集转换成Java对象,提供了4种实现类。
- BeanHandler 将结果集映射成Java对象
- BeanListHandler 将结果集映射成List集合
- MapHandler 将结果集映射成Map对象
- MapListHandler 将结果接映射成MapList集合
2 使用
// 查询所有学生
public List<Student> findAll() {
Connection connection = JDBCTool.getConnection();
String sql = "select * from student";
// 接收查询结果的集合
List<Student> studentList = new ArrayList<>();
try {
// DBUtil提供的执行类
QueryRunner queryRunner = new QueryRunner();
// query方法中执行查询语句,并解析结果集返回
studentList = queryRunner.query(connection, sql, new BeanListHandler<>(Student.class));
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCTool.close(null, null, connection);
}
return studentList;
}
使用 DBUtil 提供的 QueryRunner.query() 传入Connection, Sql,和想转换Class信息等参数,实现了执行sql语句自动解析结果集并返回,省去了如下操作,使代码更加简练。
// 创建执行sql语句的preparedStatement
preparedStatement = connection.prepareStatement(sql);
// 使用ResultSet接收结果
resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
Integer id = resultSet.getInt(1);
String name = resultSet.getString(2);
Integer age = resultSet.getInt(3);
String sex = resultSet.getString(4);
Student student = new Student();
student.setId(id);
student.setName(name);
student.setAge(age);
student.setSex(sex);
studentList.add(student);
System.out.println(student.toString());
}
如果说JDBCTool中省略了JDBC使用四步中的第一步、第二步,那DBUtil就通过封装,省略了第三步、第四步(创建PreparedStatement执行SQL语句、创建ResultSet对象接收查询结果并解析)。
总结
JDBCTool + DBUtil 即可完成Java数据库连接,访问数据的所有操作。
C3P0的使用可以实现数据库连接配置。