简介
JDBC(Java DataBase Connectivity)是Java与数据库的接口规范,由Java 语言编写的类和接口组成,大致分为两类:针对Java程序员的JDBC API和针对数据库开发商的低层的JDBC driver API。而JDBC驱动程序由实施了这些接口的类组成。
JDBC库包括通常与数据库使用相关的操作有:
- 连接数据库
- 创建SQL语句
- 在数据库中执行SQL语句
-
查看和修改结果记录
一、环境介绍
- 在mysql中创建一个库shen,并创建user表和插入表的数据。
- 新建一个Java工程jdbc,并导入数据驱动。
二、详细步骤
1、加载数据库驱动
//1.加载驱动(开发推荐的方式)Class.forName(\"com.mysql.jdbc.Driver\");
注意:如果连接的是SQL server
//1.加载驱动Class.forName(\"com.microsoft.jdbc.sqlserver.SQLServerDriver\");
2、建立连接
1、数据库URL
URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:
jdbc:mysql:[]//localhost:3306/shen ?参数名:参数值
常用数据库URL地址的写法:
Oracle:jdbc:oracle:thin:@localhost:1521:shen
SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=shen
MySql:jdbc:mysql://localhost:3306/shen
注意:如果是localhost:3306,mysql可以简写为jdbc:mysql:///sid(尽量不这样)
2、Connection
Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,创建方法为:
Connection conn = DriverManager.getConnection(url,user,pass);
这个对象的常用方法:
方法 | 描述 |
---|---|
createStatement() | 创建向数据库发送sql的statement对象。 |
prepareStatement(sql) | 创建向数据库发送预编译sql的PrepareSatement对象。 |
prepareCall(sql) | 创建执行存储过程的callableStatement对象。 |
setAutoCommit(boolean autoCommit) | 设置事务是否自动提交。 |
commit() | 在链接上提交事务。 |
rollback() | 在此链接上回滚事务。 |
String url = \"jdbc:mysql://localhost:3306/shen\";String username = \"shen\";String password = \"Anxin062039\";Connection conn = null;//2.获取与数据库的链接conn = DriverManager.getConnection(url, username, password);
3、执行SQL语句
1、Statement
Jdbc程序中的Statement对象用于向数据库发送SQL语句,创建方法为:
Statement st = conn.createStatement();
Statement对象常用方法:
方法 | 含义 |
---|---|
executeQuery(String sql) | 用于向数据发送查询语句。 |
executeUpdate(String sql) | 用于向数据库发送insert、update或delete语句 |
execute(String sql) | 用于向数据库发送任意sql语句 |
addBatch(String sql) | 把多条sql语句放到一个批处理中。 |
executeBatch() | 向数据库发送一批sql语句执行。 |
Statement st = null;//3.获取用于向数据库发送sql语句的statementst = conn.createStatement();//4.向数据库发sqlString sql = \"select id,name,password,email,birthday from users\";st.executeQuery(sql);
2、PreperedStatement
PreperedStatement是Statement的孩子,它的实例对象可以通过调用:
PreperedStatement st = conn.preparedStatement()
PreperedStatement st = null;String sql = \"select * from users where name=? and password=?\";//3.获取用于向数据库发送sql语句的Preperedstatementst = conn.preparedStatement(sql);//在此次传入,进行预编译st.setString(1, username);st.setString(2, password);//4.向数据库发sqlst.executeQuery();//在这里不需要传入sql
比较:相对于Statement对象而言
- PreperedStatement可以避免SQL注入的问题。
如:String sql="select * from admin where loginname=\’"+loginName+"\’ and loginpwd=\’"+loginPwd+"\’";
在应用中:
-》请输入账号:
333
-》请输入密码:
wer\’or\’1\’=\’1
实际上发送:select * from admin where loginname=\’333\’ and loginpwd=\’wer\’or\’1\’=\’1\’,登录成功!
- Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
- 并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
4、获取结果
Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式,ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。
1、获取行
ResultSet提供了对结果集进行滚动的方法:
- next():移动到下一行
- Previous():移动到前一行
- absolute(int row):移动到指定行
- beforeFirst():移动resultSet的最前面。
- afterLast() :移动到resultSet的最后面。
2、获取值
ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:
- 获取任意类型的数据
getObject(int index)
getObject(string columnName)
- 获取指定类型的数据,例如:
getString(int index)
getString(String columnName)
附加:
常用数据类型转换:
SQL类型 | Jdbc对应方法 | 返回类型 |
---|---|---|
bit(1),bit(n) | getBoolean,getBytes() | Boolean,byte[] |
tinyint | getByte() | Byte |
smallint | getShort() | Short |
int | getInt | Int |
bigint | getLong() | Long |
char,varchar,longvarchar | getString | String |
text(clob) blob | getClob(),getblob() | Clob,blob |
date | getDate() | java.sql.Date |
time | getTime() | java.sql.Time |
timestamp | getTimestamp | java.sql.Timestamp |
ResultSet rs = null;//4.向数据库发sql,并获取代表结果集的resultsetString sql = \"select id,name,password,email,birthday from users\";rs = st.executeQuery(sql);//5.取出结果集的数据rs.afterLast();rs.previous();System.out.println(\"id=\" + rs.getObject(\"id\"));System.out.println(\"name=\" + rs.getObject(\"name\"));System.out.println(\"password=\" + rs.getObject(\"password\"));System.out.println(\"email=\" + rs.getObject(\"email\"));System.out.println(\"birthday=\" + rs.getObject(\"birthday\"));
或者:
//循环取出(id)while(rs.next()){String id=rs.getString(1);//1代表数据库中表的列数,id在第一列也可以(\"id\")!!!System.out.println(id+\" \");}
5、释放资源
Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。
注意:为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
//6.关闭链接,释放资源if(rs!=null){try{rs.close();}catch (Exception e) {e.printStackTrace();}rs = null;}if(st!=null){try{st.close();}catch (Exception e) {e.printStackTrace();}}if(conn!=null){try{conn.close();}catch (Exception e) {e.printStackTrace();}}
三、基本操作
1、DDL
/*** 在java中使用ddl语句(credate,drop,backup...)*/package com.shen.study2;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;public class Test1 {public static void main(String[] args) {// TODO Auto-generated method stubTest1 test=new Test1();}public Test1(){this.lianjie();}public void lianjie(){//定义需要的对象PreparedStatement ps=null;Connection ct=null;ResultSet rs=null;try {//初始化对象//1.加载驱动Class.forName(\"com.microsoft.jdbc.sqlserver.SQLServerDriver\");//2.得到连接(1433表示sql server的默认端口)ct=DriverManager.getConnection(\"jdbc:microsoft:sqlserver://localhost:1433;databaseName=shen\",\"sa\",\"Anxin062039\");//3.创建Preparestatement,创建数据ps=ct.prepareStatement(\"create database vvv\");// ps=ct.prepareStatement(\"create table xxx\");//创建表// ps=ct.prepareStatement(\"backup database shen to disk=\'F:/123.bak\'\");//备份数据库//如果执行的是ddl语句boolean b=ps.execute();if(b){System.out.println(\"创建成功!\");}else {System.out.println(\"失败\");}} catch (Exception e) {// TODO: handle exception}finally {//关闭资源try {//为了程序健壮if(ps!=null)ps.close();if(ct!=null)ct.close();} catch (Exception e2) {// TODO: handle exception}}}}
2、CRUD
实例:user
public class User {private int id;private String name;private String password;private String email;private Date birthday;//相关的get和set}
连接工具:JdbcUtils
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 {private static String driver = null;private static String url = null;private static String username = null;private static String password = null;static{try{InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream(\"db.properties\");Properties prop = new Properties();prop.load(in);driver = prop.getProperty(\"driver\");url = prop.getProperty(\"url\");username = prop.getProperty(\"username\");password = prop.getProperty(\"password\");Class.forName(driver);}catch (Exception e) {throw new ExceptionInInitializerError(e);}}public static Connection getConnection() throws SQLException{return DriverManager.getConnection(url, username,password);}public static void release(Connection conn,Statement st,ResultSet rs){if(rs!=null){try{rs.close();}catch (Exception e) {e.printStackTrace();}rs = null;}if(st!=null){try{st.close();}catch (Exception e) {e.printStackTrace();}}if(conn!=null){try{conn.close();}catch (Exception e) {e.printStackTrace();}}}}
资源文件:db.properties
#driver=com.mysql.jdbc.Driver#url=jdbc:mysql://localhost:3306/shen#username=shen#password=Anxin062039
注意:前面添加#,表示注释。如果改成SQL server直接更改这里即可
功能实现:Demo
import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;import org.junit.Test;import cn.itcast.utils.JdbcUtils;//使用jdbc对数据库增删改查public class Demo {@Testpublic void insert(){Connection conn = null;Statement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();st = conn.createStatement();String sql = \"insert into users(id,name,password,email,birthday) values(4,\'xxx\',\'123\',\'[email protected]\',to_date(\'1980-09-09\',\'YYYY-MM-DD\'))\";int num = st.executeUpdate(sql); //updateif(num>0){System.out.println(\"插入成功!!\");}}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}@Testpublic void delete(){Connection conn = null;Statement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"delete from users where id=4\";st = conn.createStatement();int num = st.executeUpdate(sql);if(num>0){System.out.println(\"删除成功!!\");}}catch (Exception e) {}finally{JdbcUtils.release(conn, st, rs);}}@Testpublic void update(){Connection conn = null;Statement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"update users set name=\'wuwang\',email=\'[email protected]\' where id=3\";st = conn.createStatement();int num = st.executeUpdate(sql);if(num>0){System.out.println(\"更新成功!!\");}}catch (Exception e) {}finally{JdbcUtils.release(conn, st, rs);}}@Testpublic void find(){Connection conn = null;Statement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"select * from users where id=1\";st = conn.createStatement();rs = st.executeQuery(sql);if(rs.next()){System.out.println(rs.getString(\"name\"));}}catch (Exception e) {}finally{JdbcUtils.release(conn, st, rs);}}}
四、常见操作
1、处理大数据
如下内容都借助CRUD中的内容
1.存取文本文件(.txt文件)
clob用于存储大文本(mysql中无clob,存储大文本采用的是Text)
数据库为:
create table testclob(id int primary key auto_increment,resume text);public class Demo1 {@Testpublic void add() {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"insert into testclob(resume) values(?)\"st = conn.prepareStatement(sql);//Reader reader = new InputStreamReader(Demo1.class.getClassLoader().getResourceAsStream(\"1.txt\"));String path = Demo1.class.getClassLoader().getResource(\"1.txt\").getPath();//1.txt文件在src下File file = new File(path);st.setCharacterStream(1, new FileReader(file), (int) file.length());//将该文件添加int num = st.executeUpdate();if(num>0){System.out.println(\"插入成功!!\");}}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}@Testpublic void read(){Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"select resume from testclob where id=1\";st = conn.prepareStatement(sql);rs = st.executeQuery();if(rs.next()){System.out.println(\"haha\");Reader reader = rs.getCharacterStream(\"resume\");char buffer[] = new char[1024];int len = 0;FileWriter out = new FileWriter(\"c:\\\\1.txt\");while((len=reader.read(buffer))>0){out.write(buffer, 0, len)}out.close();reader.close();}}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}}
2.存取二进制文件(图片,视频)
数据库:
create table testblob(id int primary key auto_increment,image longblob);public class Demo2 {@Testpublic void add(){Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"insert into testblob(image) values(?)\";st = conn.prepareStatement(sql);String path = Demo2.class.getClassLoader().getResource(\"01.jpg\").getPath();st.setBinaryStream(1, new FileInputStream(path), (int) new File(path).length());int num = st.executeUpdate();if(num>0){System.out.println(\"插入成功!!\");}}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}@Testpublic void read(){Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"select image from testblob where id=?\";st = conn.prepareStatement(sql);st.setInt(1, 1);rs = st.executeQuery();if(rs.next()){InputStream in = rs.getBinaryStream(\"image\");int len = 0;byte buffer[] = new byte[1024];FileOutputStream out = new FileOutputStream(\"c:\\\\1.jpg\");while((len=in.read(buffer))>0){out.write(buffer,0, len);}in.close();out.close();}}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}}
2、批量处理SQL
数据库:
create table testbatch(id int primary key,name varchar2(20));
1.通过Statement
@Testpublic void testbatch1(){Connection conn = null;Statement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql1 = \"insert into testbatch(id,name) values(1,\'aaa\')\";String sql2 = \"insert into testbatch(id,name) values(2,\'bbb\')\";String sql3 = \"delete from testbatch where id=1\";st = conn.createStatement();st.addBatch(sql1);st.addBatch(sql2);st.addBatch(sql3);st.executeBatch();st.clearBatch();}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}
2.通过preparedstatement
@Testpublic void testbatch2(){long starttime = System.currentTimeMillis();Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"insert into testbatch(id,name) values(?,?)\";st = conn.prepareStatement(sql);for(int i=1;i<10000008;i++){ //i=1000 2000st.setInt(1, i);st.setString(2, \"aa\" + i);st.addBatch();if(i%1000==0){st.executeBatch();st.clearBatch();}}st.executeBatch();}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}long endtime = System.currentTimeMillis();System.out.println(\"程序花费时间:\" + (endtime-starttime)/1000 + \"秒!!\");}
3、获取自动生成的主键
数据库:
create table test1(id int primary key auto_increment,//id自动生成name varchar(20));public class Demo4 {/*** 获取自动生成的主键*/public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();String sql = \"insert into test1(name) values(?)\";st = conn.prepareStatement(sql);st.setString(1, \"aaa\");//在插入name时数据库会自动生成idst.executeUpdate();rs = st.getGeneratedKeys();//获取生成的主键if(rs.next()){System.out.println(rs.getInt(1));}}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}}
4、调用存储过程
public class Demo5 {/**jdbc调用存储过程create procedure p_course_insert@c_no nvarchar(50),@c_name nvarchar(50),@t_name nvarchar(50)asinsert into t_course(c_no,c_name,t_name)values(@c_no,@c_name,@t_name)*/public static void main(String[] args) {Connection conn = null;CallableStatement cs = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();cs = conn.prepareCall(\"{call p_course_inser(?,?,?)}\");cs.setString(1, \"xxxxx\");cs.registerOutParameter(2, Types.VARCHAR);cs.execute();String result = cs.getString(2);System.out.println(result);}catch (Exception e) {e.printStackTrace();}finally{JdbcUtils.release(conn, cs, rs);}}}
5、使用事务
1.普通事务的操作
/*** 模似转帐create table account(id int primary key auto_increment,name varchar(40),money float)character set utf8 collate utf8_general_ci;insert into account(name,money) values(\'aaa\',1000);insert into account(name,money) values(\'bbb\',1000);insert into account(name,money) values(\'ccc\',1000);*/public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try{conn = JdbcUtils.getConnection();conn.setAutoCommit(false); //start transaction,开启事务String sql1 = \"update account set money=money-100 where name=\'aaa\'\";st = conn.prepareStatement(sql1);st.executeUpdate();String sql2 = \"update account set money=money+100 where name=\'bbb\'\";st = conn.prepareStatement(sql2);st.executeUpdate();conn.commit();//提交System.out.println(\"成功!!!\"); //log4j}catch (Exception e) {e.printStackTrace();//如果程序出错手动回滚}finally{JdbcUtils.release(conn, st, rs);}}
2.设置事务回滚点
public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;Savepoint sp = null;try{conn = JdbcUtils.getConnection();conn.setAutoCommit(false); //start transactionString sql1 = \"update account set money=money-100 where name=\'aaa\'\";st = conn.prepareStatement(sql1);st.executeUpdate();sp = conn.setSavepoint();//在这里设置事务回滚点String sql2 = \"update account set money=money+100 where name=\'bbb\'\";st = conn.prepareStatement(sql2);st.executeUpdate();int x = 1/0;String sql3 = \"update account set money=money+100 where name=\'ccc\'\";st = conn.prepareStatement(sql3);st.executeUpdate();conn.commit();}catch (Exception e) {try {conn.rollback(sp);//回滚到该事务点,即该点之前的会正常执行(sql1)conn.commit(); //回滚了要记得提交,如果没有提交sql1将会自动回滚} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}e.printStackTrace();}finally{JdbcUtils.release(conn, st, rs);}}
3.设置事务隔离级别
conn = JdbcUtils.getConnection();conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//避免脏读conn.setAutoCommit(false);/*Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)Read committed:可避免脏读情况发生(读已提交)。Read uncommitted:最低级别,以上情况均无法保证。(读未提交)*/
五、使用数据库连接池
1、原因
1.传统连接方法
缺点:
用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。
2.数据库连接池
2、开源连接池
1.DBCP 数据库连接池
工具类如下:JdbcUtils_DBCP
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;import javax.sql.DataSource;import org.apache.commons.dbcp.BasicDataSourceFactory;public class JdbcUtils_DBCP {private static DataSource ds = null;static{try{InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream(\"dbcpconfig.properties\");Properties prop = new Properties();prop.load(in);BasicDataSourceFactory factory = new BasicDataSourceFactory();ds = factory.createDataSource(prop);System.out.println(ds);}catch (Exception e) {throw new ExceptionInInitializerError(e);}}public static Connection getConnection() throws SQLException{return ds.getConnection();}public static void release(Connection conn,Statement st,ResultSet rs){if(rs!=null){try{rs.close();}catch (Exception e) {e.printStackTrace();}rs = null;}if(st!=null){try{st.close();}catch (Exception e) {e.printStackTrace();}}if(conn!=null){try{conn.close();}catch (Exception e) {e.printStackTrace();}}}}
2.C3P0 数据库连接池
连接工具类:JdbcUtils_C3p0(自己在这里更改)
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;import javax.sql.DataSource;import org.apache.commons.dbcp.BasicDataSourceFactory;import com.mchange.v2.c3p0.ComboPooledDataSource;public class JdbcUtils_C3P0 {private static ComboPooledDataSource ds = null;static{try{ds = new ComboPooledDataSource();ds.setDriverClass(\"com.mysql.jdbc.Driver\");ds.setJdbcUrl(\"jdbc:mysql://localhost:3306/day16\");ds.setUser(\"root\");ds.setPassword(\"root\");ds.setInitialPoolSize(10);//最初连接数ds.setMinPoolSize(5);//最小连接数ds.setMaxPoolSize(20);//最大连接数}catch (Exception e) {throw new ExceptionInInitializerError(e);}}public static Connection getConnection() throws SQLException{return ds.getConnection();}public static void release(Connection conn,Statement st,ResultSet rs){if(rs!=null){try{rs.close();}catch (Exception e) {e.printStackTrace();}rs = null;}if(st!=null){try{st.close();}catch (Exception e) {e.printStackTrace();}}if(conn!=null){try{conn.close();}catch (Exception e) {e.printStackTrace();}}}}
也可以将配置信息放在xml文件中(src下):c3p0-config.xml
<?xml version=\"1.0\" encoding=\"UTF-8\"?><c3p0-config><default-config><property name=\"driverClass\">com.mysql.jdbc.Driver</property><property name=\"jdbcUrl\">jdbc:mysql://localhost:3306/day16</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><named-config name=\"mysql\"><property name=\"driverClass\">com.mysql.jdbc.Driver</property><property name=\"jdbcUrl\">jdbc:mysql://localhost:3306/day16</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><named-config name=\"oracle\"><property name=\"driverClass\">com.mysql.jdbc.Driver</property><property name=\"jdbcUrl\">jdbc:mysql://localhost:3306/day16</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>
这样JdbcUtils_C3p0可以改为:
/*ds = new ComboPooledDataSource();ds.setDriverClass(\"com.mysql.jdbc.Driver\");ds.setJdbcUrl(\"jdbc:mysql://localhost:3306/day16\");ds.setUser(\"root\");ds.setPassword(\"root\");ds.setInitialPoolSize(10);//最初连接数ds.setMinPoolSize(5);//最小连接数ds.setMaxPoolSize(20);//最大连接数*/ds = new ComboPooledDataSource(\"\"mysql\"\");//如果默认()