JDBC
1. JDBC介绍
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC;这套接口由数据库厂商去实现,这样,开发人员只需要学习jdbc接口,并通过JDBC加载具体的驱动,就可以操作数据库;
JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成;组成JDBC的2个包:java.sql、javax.sql开发JDBC应用需要以上2个包的支持外,还需要导入相应JDBC的数据库实现(即数据库驱动);
2. 注册JDBC
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public static void main(String[] args) throws Exception{
String url ="jdbc:mysql://localhost:3306/jdbcStudy?";
String username = "root";
String password = "root";
String sql = "select id,name,sroce,message from t_student WHERE id = 1";
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接
Connection connection = DriverManager.getConnection(url,username,password);
//3.获取向数据库发送SQL语句的statement运输工具
Statement statement = connection.createStatement();
//4.发送SQL语句并返回一个结果集
ResultSet resultSet = statement.executeQuery(sql);
//5.遍历获取的结果
while (resultSet.next()){
System.out.println("id=" + resultSet.getObject("id"));//id=1
System.out.println("name=" + resultSet.getObject("name"));//name=小郭
System.out.println("sroce=" + resultSet.getObject("sroce"));//sroce=100
System.out.println("message=" + resultSet.getObject("message"));//message=青岛
}
//6.关闭资源
resultSet.close();
statement.close();
connection.close();
}
3. 常用类说明
3.1 DriverManager类
JDBC程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:
DriverManager.getConnection(url,user,password);
DriverManager.registerDriver(new Driver());----->//不推荐使用
//1.查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象
//2.程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦
推荐方式:Class.forName(“com.mysql.jdbc.Driver”);采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高
3.2 数据库URL类
URL用于标识数据库的位置,通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:
①Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
②SqlServer写法:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
③MySql写法:jdbc:mysql://localhost:3306/sid
3.3 Connection类
JDBC程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法:
方法 | 说明 |
---|---|
createStatement() | 创建向数据库发送sql的statement对象 |
prepareStatement(sql) | 创建向数据库发送预编译sql的PrepareSatement对象 |
setAutoCommit(boolean autoCommit) | 设置事务是否自动提交 |
commit() | 在链接上提交事务 |
rollback() | 在此链接上回滚事务 |
3.4 Statement类
JDBC程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:
方法 | 说明 |
---|---|
executeQuery(String sql) | 用于向数据发送查询语句 |
executeUpdate(String sql) | 用于向数据库发送insert、update或delete语句 |
execute(String sql) | 用于向数据库发送任意sql语句 |
addBatch(String sql) | 把多条sql语句放到一个批处理中 |
executeBatch() | 向数据库发送一批sql语句执行 |
3.5 ResultSet类
一、JDBC程序中的ResultSet用于代表Sql语句的执行结果;Resultset封装执行结果时,采用的类似于表格的方式;ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据;
//实现ResultSet
ResultSet resultSet = statement.executeQuery(sql);
//遍历获取的结果
while (resultSet.next()){
System.out.println("id=" + resultSet.getObject("id"));
System.out.println("name=" + resultSet.getObject("name"));
System.out.println("password=" + resultSet.getObject("sroce"));
System.out.println("email=" + resultSet.getObject("message"));
}
二、ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法
获取任意类型的数据 | 获取指定类型的数据 | ResultSet还提供了对结果集进行滚动的方法 |
---|---|---|
getObject(int index) | getString(int index) | next():移动到下一行 |
getObject(string columnName) | getString(String columnName) | Previous():移动到前一行 |
- | - | absolute(int row):移动到指定行 |
- | - | beforeFirst():移动resultSet的最前面 |
- | - | afterLast() :移动到resultSet的最后面 |
3.6 释放资源
①JDBC程序运行完后,切记要释放创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象
②特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机
③Connection的使用原则是尽量晚创建,尽量早的释放
④为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中
4. CRUD操作
①JDBC中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可
②Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,返回一个整数(即增删改语句导致了数据库几行数据发生了变化)
③Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象
//使用executeUpdate插入数据
Statement statement = connection.createStatement();
String sql = "INSERT INTO t_student(id,name,sroce,message) VALUES(5,'小王',93,'菏泽')" ;
int num = statement.executeUpdate(sql);
if(num>0){
System.out.println("插入成功");
}
System.out.println(num);//1
//使用executeUpdate删除数据
Statement statement = connection.createStatement();
String sql = "delete from t_student where id=5" ;
int num = statement.executeUpdate(sql);
if(num>0){
System.out.println("删除成功");
}
System.out.println(num);//1
//使用executeUpdate修改数据
Statement statement = connection.createStatement();
String sql = "UPDATE t_student SET score=100 WHERE name='小郭'";
int num = statement.executeUpdate(sql);
if(num>0){
System.out.println("修改成功");
}
System.out.println(num);//1
//使用executeQuery查询数据
Statement statement = connection.createStatement();
String sql = "SELECT id,name,sroce FROM t_student WHERE name ='小郭' AND sroce = 95 ";
ResultSet resultSet = statement.executeQuery(sql);
While(resultset.next()){
//根据获取列的数据类型,分别调用resultSet的方法映射到java对象中
}
5. JDBC操作数据库
一、新建db.properties配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcStudy?
useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=root
二、新建JdbcUtils工具类
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JdbcUtils {
//初始化JDBC信息
private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;
static {
try {
//输入流读取db.properties
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(inputStream);
//获取db.properties
driver = properties.getProperty(driver);
url = properties.getProperty(url);
username = properties.getProperty(username);
password = properties.getProperty(password);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//获取数据库驱动连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//关闭资源
public static void exit(Connection connection,Statement statement,ResultSet resultSet) throws SQLException {
if (resultSet != null){
resultSet.close();
}
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
}
}
三、新建TestInsert类
/*其他CRUD同理*/
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestInsert {
public static void main(String[] args) throws SQLException {
//初始化数据库交互对象
Connection connection = null;
Statement statement = null;
ResultSet resultset = null;
try{
//获取一个数据库连接
connection = JdbcUtils.getConnection();
//通过conn对象获取负责执行SQL命令的Statement对象
statement = connection.createStatement();
//执行的SQL命令
String sql = "INSERT INTO t_student(id,name,sroce,message) VALUES(5,'小王',93,'菏泽')" ;
//执行插入操作,executeUpdate方法返回成功的条数
int num = statement.executeUpdate(sql);
if(num>0){
System.out.println("添加信息成功,"+"本次插入影响"+num+"行");
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//SQL执行完成之后释放相关资源
JdbcUtils.exit(connection, statement, resultset);
}
}
}
6. PreparedStatement
①PreperedStatement是Statement的子类,它的实例对象可以通过调用Connection.preparedStatement()方法获得
②相对于Statement对象而言:PreperedStatement可以避免SQL注入的问题
③Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出
④PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率
⑤PreperedStatement对于SQL中的参数,允许使用占位符的形式进行替换,简化SQL语句的编写
/*使用PreparedStatement对象完成对数据库的CRUD操作*/
//插入数据,其他同理
import java.sql.Connection;
import java.util.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class TestInsert {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparestatement = null;
ResultSet resultset = null;
try{
//获取一个数据库连接
connection = JdbcUtils.getConnection();
//预编译要执行的SQL命令,SQL中的参数使用?作为占位符
//使用占位符后,重新进行替换,简化SQL语句编写
String sql = "INSERT INTO t_student(id,name,sroce,message) VALUES(?,?,?,?)";
//通过conn对象获取负责执行SQL命令的prepareStatement对象
preparestatement = connection.prepareStatement(sql);
//为SQL语句中的参数赋值
//注意,索引是从1开始的
preparestatement.setInt(1, 4);//id为int类型
preparestatement.setString(2, "小王");//name为varchar类型
preparestatement.setString(3, "80");//sroce为varchar类型
preparestatement.setString(4, "青岛");//message为varchar类型
//执行插入操作,executeUpdate方法返回成功的条数
int num = preparestatement.executeUpdate();
if(num>0){
System.out.println("添加信息成功,"+"本次插入影响"+num+"行");
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//SQL执行完成之后释放相关资源
JdbcUtils.release(conncetion, preparestatement, resultset);
}
}
}
7. SQL注入
一、原因
用户输入的数据中有SQL关键字或语句并且参与了SQL语句的编译,导致SQL语句编译后的条件含义为True,实现欺骗服务器,一直得到正确的结果;
二、如何避免
不要使用SQL拼接方式,SQL语句要在用户输入数据前就已经编译成完整的SQL语句,不再进行填充
public static void main(String[] args) {
login("xiaoguo","12345"); // 正常登陆
login("'or '1=1","12345"); // SQL注入,通过OR关键字使条件在用户名密码不正确的时候仍然成立
}
8. 事务
/*程序实现MySQL中转账案例*/
//模拟转账成功时的业务场景
import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class TestTransaction1 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedstatement = null;
ResultSet resultset = null;
try{
connection = JdbcUtils.getConnection();
//通知数据库开启事务(start transaction)
connection.setAutoCommit(false);
String sql1 = "update account set money=money-100 where name='A'";
preparedstatement = connection.prepareStatement(sql1);
//更新数据
preparedstatement.executeUpdate();
String sql2 = "update account set money=money+100 where name='B'";
preparedstatement = connection.prepareStatement(sql2);
//更新数据
preparedstatement.executeUpdate();
//上面的两条SQL执行Update语句成功之后就通知数据库提交事务
connection.commit();
//log4j
System.out.println("任务已结束");
}catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(connection, preparedstatement, resultset);
}
}
}
//模拟转账过程中出现异常导致有一部分SQL执行失败后让数据库自动回滚事务
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class TestTransaction2 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedstatement = null;
ResultSet resultset = null;
try{
connection = JdbcUtils.getConnection();
//通知数据库开启事务(start transaction)
connection.setAutoCommit(false);
String sql1 = "update account set money=money-100 where name='A'";
preparedstatement = connection.prepareStatement(sql1);
//更新数据
preparedstatement.executeUpdate();
//用这句代码模拟执行完SQL1语句之后程序出现了异常而导致后面的SQL无法正常执行,事务也无法正常提交,此时数据库会自动执行回滚操作
int x = 1/0;
String sql2 = "update account set money=money+100 wherename='B'";
preparedstatement = connection.prepareStatement(sql2);
//更新数据
preparedstatement.executeUpdate();
//上面的两条SQL执行Update语句成功之后就通知数据库提交事务
connection.commit();
System.out.println("任务已结束");
}catch (Exception e) {
e.printStackTrace();
}finally{
//任务结束,释放资源
JdbcUtils.release(connection, preparedstatement, resultset);
}
}
}
//模拟转账过程中出现异常导致有一部分SQL执行失败时手动通知数据库回滚事务
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestTransaction3 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedstatement = null;
ResultSet resultset = null;
try{
connection = JdbcUtils.getConnection();
//通知数据库开启事务(start transaction)
connection.setAutoCommit(false);
String sql1 = "update account set money=money-100 where name='A'";
preparedstatement = connection.prepareStatement(sql1);
//更新数据
preparedstatement.executeUpdate();
//用这句代码模拟执行完SQL1语句之后程序出现了异常而导致后面的SQL无法正常执行,事务也无法正常提交
String sql2 = "update account set money=money+100 where name='B'";
preparedstatement = conn.prepareStatement(sql2);
//更新数据
preparedstatement.executeUpdate();
//上面的两条SQL执行Update语句成功之后就通知数据库提交事务
connection.commit();
System.out.println("任务已完成");
}catch (Exception e) {
try {
//捕获到异常之后手动通知数据库执行回滚事务的操作
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally{
//任务结束,释放资源
JdbcUtils.release(connection, preparedstatement, resultset);
}
}
}
9. 数据库连接池
9.1 概述
①数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标
②数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个;
③数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的;
④无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量;
⑤连接池最大数据库连接数量限定了连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,请求将被加入到等待队列中;
9.2 连接池设定问题
一、最小连接数
连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费
二、最大连接数
连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
三、如果最小连接数与最大连接数相差很大
那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接;这些大于最小连接数的数据库连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是空间超时后被释放
9.3 开源数据库连接池
现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的实现,即连接池的实现;通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现;在使用了数据库连接池之后,在项目的实际开发中就不需要编写连接数据库的代码了,直接从数据源获得数据库的连接
9.3.1 DBCP数据源
DBCP 是 Apache 软件基金组织下的开源连接池实现,Tomcat 的连接池正是采用该连接池来实现的;该数据库连接池既可以与应用服务器整合使用,也可由
应用程序独立使用;要使用DBCP数据源,需要应用程序应在系统中增加如下两个 Jar文件:①Commons-dbcp.jar:连接池的实现 ②Commons-pool.jar:连接池实现的依赖库
一、新建dbcpconfig.properties
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名='值';]
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcStudy?
useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的连接的自动提交状态
defaultAutoCommit=true
#driver default指定由连接池所创建的连接的只读状态
#driver default=read-only
#如果没有设置该值,则“setReadOnly”方法将不被调用(某些驱动并不支持只读模式,如:Informix)
default ReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)
#可用值为下列之一:NONE,READ_UNCOMMITTED, READ_COMMITTED(见javadoc)
REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
二、JdbcUtils_DBCP工具类
/**
* 在Java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现
* DBCP连接池就是java.sql.DataSource接口的一个具体实现
*/
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class JdbcUtils_DBCP {
private static DataSource datasource = null;
//在静态代码块中创建数据库连接池
static{
try{
//加载dbcpconfig.properties配置文件
InputStream inputstrem =JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties properties = new Properties();
properties.load(inputstream);
//创建数据源
datasource = BasicDataSourceFactory.createDataSource(properties);
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
//从数据源中获取数据库连接
public static Connection getConnection() throws SQLException{
return datasource.getConnection();
}
//释放资源
public static void release(Connection connection,Statement statement,ResultSet resultset){
if(resultset!=null){
try{
//关闭存储查询结果的ResultSet对象
resultset.close();
}catch (Exception e) {
e.printStackTrace();
}
resultset = null;
}
if(statement!=null){
try{
//关闭负责执行SQL命令的Statement对象
statement.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(connection!=null){
try{
//将Connection连接对象还给数据库连接池
connection.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
三、新建测试类
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
public class DBCPTest {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparestatement = null;
ResultSet resultset = null;
try{
//获取数据库连接
connection = JdbcUtils_DBCP.getConnection();
String sql = "INSERT INTO t_student(id,name,sroce,message) VALUES(?,?,?,?)";
//通过conn对象获取负责执行SQL命令的prepareStatement对象
preparestatement = connection.prepareStatement(sql);
//为SQL语句中的参数赋值
//注意索引是从1开始的
preparestatement.setInt(1, 4);//id为int类型
preparestatement.setString(2, "小王");//name为varchar类型
preparestatement.setString(3, "80");//sroce为varchar类型
preparestatement.setString(4, "青岛");//message为varchar类型
//执行插入操作,executeUpdate方法返回成功的条数
int num = preparestatement.executeUpdate();
if(num>0){
System.out.println("添加信息成功,"+"本次插入影响"+num+"行");
}
}catch (Exception e){
e.printStackTrace();
}finally{
//SQL执行完成之后释放相关资源
JdbcUtils.release(conncetion, preparestatement, resultset);
}
}
}
9.3.2 C3P0数据源
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展;目前使用它的开源项目有Hibernate,Spring等;C3P0数据源在项目开发中使用得比较多
C3P0与DBCP区别:DBCP没有自动回收空闲连接的功能、C3P0有自动回收空闲连接功能
一、新建c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!--
C3P0的缺省(默认)配置
1.如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”
2.这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcStudy?</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<!--
C3P0的命名配置
1.如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”
2.这样写就表示使用的是name是MySQL的配置信息来创建数据源
-->
<named-config name="MySQL">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcStudy?</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
二、创建工具类
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.mchange.v2.c3p0.ComboPooledDataSource;
//数据库连接工具类
public class JdbcUtils_C3P0 {
private static ComboPooledDataSource ds = null;
//在静态代码块中创建数据库连接池
static{
try{
//方式一:通过代码创建C3P0数据库连接池
/**
*ds = new ComboPooledDataSource();
*ds.setDriverClass("com.mysql.jdbc.Driver");
*ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcstudy");
*ds.setUser("root");
*ds.setPassword("root");
*ds.setInitialPoolSize(10);
*ds.setMinPoolSize(5);
*ds.setMaxPoolSize(20);
*/
//方式二:通过读取C3P0的xml配置文件创建数据源,C3P0的xml配置文件c3p0-config.xml必须放在src目录下
//ds = new ComboPooledDataSource();//使用C3P0的默认配置来创建数据源
ds = new ComboPooledDataSource("MySQL");//使用C3P0的命名配置来创建数据源
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
//从数据源中获取数据库连接
public static Connection getConnection() throws SQLException{
return datasource.getConnection();
}
//释放资源
public static void release(Connection connection,Statement statement,ResultSet resultset){
if(resultset!=null){
try{
//关闭存储查询结果的ResultSet对象
resultset.close();
}catch (Exception e) {
e.printStackTrace();
}
resultset = null;
}
if(statement!=null){
try{
//关闭负责执行SQL命令的Statement对象
statement.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(connection!=null){
try{
//将Connection连接对象还给数据库连接池
connection.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
三、测试类
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
public class DBCPTest {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparestatement = null;
ResultSet resultset = null;
try{
//获取数据库连接
connection = JdbcUtils_C3P0.getConnection();
String sql = "INSERT INTO t_student(id,name,sroce,message) VALUES(?,?,?,?)";
//通过conn对象获取负责执行SQL命令的prepareStatement对象
preparestatement = connection.prepareStatement(sql);
//为SQL语句中的参数赋值
//注意索引是从1开始的
preparestatement.setInt(1, 4);//id为int类型
preparestatement.setString(2, "小王");//name为varchar类型
preparestatement.setString(3, "80");//sroce为varchar类型
preparestatement.setString(4, "青岛");//message为varchar类型
//执行插入操作,executeUpdate方法返回成功的条数
int num = preparestatement.executeUpdate();
if(num>0){
System.out.println("添加信息成功,"+"本次插入影响"+num+"行");
}
}catch (Exception e){
e.printStackTrace();
}finally{
//SQL执行完成之后释放相关资源
JdbcUtils.release(conncetion, preparestatement, resultset);
}
}
}