jdbc编程基础-1

Posted benjerry

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdbc编程基础-1相关的知识,希望对你有一定的参考价值。

我们给JdbcUtil增加一个结果解析的方法

    public static List<Map<String, Object>> convertToMap(ResultSet resultSet) 
        List<Map<String, Object>> list = new ArrayList<>();
        while(true) 
            try 
                if (!resultSet.next()) break;
             catch (SQLException e) 
                e.printStackTrace();
            
            Map<String, Object> map = new HashMap<>();

            ResultSetMetaData metaData = null;
            try 
                metaData = resultSet.getMetaData();
                int columnCount = metaData.getColumnCount();
                for(int i = 1; i <= columnCount; i ++) 
                    String columnName = metaData.getColumnName(i);
                    int columnType = metaData.getColumnType(i);
                    switch (columnType) 
                        case 4: map.put(columnName, resultSet.getInt(i)); break;
                        case 12: map.put(columnName, resultSet.getString(i)); break;
                        default:
                    
                
             catch (SQLException e) 
                e.printStackTrace();
            
            list.add(map);
        
        return list;
    

 

MySQL 数据库与JDBC编程

第13章 MySQL 数据库与JDBC编程

13.1 JDBC基础

JDBC 它是一种可以执行SQL语句的java API (可以跨平台 跨数据库)

 

13.1.2 JDBC驱动

数据库驱动程序是JDBC程序数据库之间的转换层,数据库驱动程序负责将JDBC调用映射成特定的数据库调用

JDBC 驱动通常有如下4

1. 称为 JDBC-ODBC桥最早实现JDBC的驱动 (java 8 已删)

2. 直接将JDBC API 映射成数据库特定的客户端API

3.JDBC驱动 支持三层JDBC访问方式

4.纯java的 直接与数据库实例交换

 

13.2 SQL语句

按时间顺序出现了如下的几种类型数据库

1.网状型数据库

2.层次型数据库

3.关系数据库

4.面向对象数据库

 

对于关系数据库而言,最基本的数据存储单元就是数据表

数据表是存储数据的逻辑单元每一行被称为一条数据 一列被称为一个字段

 

13.2.3 SQL语句基础

SQL Structured Query Language , 结构化查询语言)

标准的SQL语言通常可以分为如下几种类型

1. 查询语句 主要有select关键字完成

2. DMLData Manipulation Language,数据库操作语言) 主要由insert update delete三个关键字完成

3. DDLData DefinitionLanguage ,数据库定义语言)主要有create alter droptruncate关键字完成

4. DCLData Control Language ,数据库控制语言)主要由grant revoke关键字完成

5. 事务控制语言 主要由commit rollback savepoint 三个关键字完成

 

13.2.4 DDL语句

几种常见的数据库对象

表        table        表示数据库的逻辑单元

数据字典         (就是系统表,存放数据库相关的信心的表通常都是由数据库系统维护)

约束      constraint     执行数据校验规则

试图      view         一个或多个数据表里的数据逻辑显示

索引      index        用于提高查询性能,相当于书的目标

函数     function      用于完成一次特定的计算,具有一个返回值

存储过程 procedure    用于完成一次完整的业务处理,没有返回值,但可通过传出参数将                  多个值传给调用环境

触发器   trigger       相当于一个时间监听器

 

1.在创建表时 如果需要指定默认值 使用 default 而不是 =

 

2 修改表结构的语法

修改表使用 alter table 修改表的结构包括增加列的定义,修改列的定义,删除列,重命名列等操作

sql中的字符串使用的是单引号

增加字段时需要注意 如果数据表中已有数据记录,除非给新增的指定默认值,否则新增的数据列不嗯给你指定非空约束,因为新增的列肯定是空

修改 modify xx int

 

删除列 drop xx

重命名 alter table 表明   rename to

删除表的语法 drop table 表名

删除数据表的效果如下

1.表结构被删除,表对象不存在

2.表里的所有数据也被删除

3.该表所有相关索引,约束也被删除

 

4 truncate 表 删除表里的全部数据,但是保留表结构

 

13.2.5 数据库约束

通过约束可以保证数据库里的数据的完整性,除此之外 当表中的数据存在相互依赖性是,可保护相关的数据不被删除

 

大部分数据库支持下面5中约束

NOT NULL 非空约束

UNIQUE 唯一约束

PRIMARY KEY 主键 表示该列可以唯一的标示该条记录

FORERGN KEY 外键 指定该行记录从属于主表中的一条记录

CHECK 检查 用于指定对应列必须满足该表达式

 

虽然约束作用是保证数据表里的数据完整性,但是约束也是数据库对象,并被保存在系统表之中

根据约束对数据列的限制 约束分为如下两类

1. 单列约束

2. 多列约束

 

为数据表指定约束有如下两个时机

1.建表的同时为相应的数据列指定约束

2.建表后创建

 

1. NOT NULL 非空约束

SQL中所有类型的值都可以为null

只能用为列级约束使用

在定义列的后增加 not null

 

2.UNIQUE 唯一约束

唯一约束用于保证定义类或者指定列的组合不允许出现重复值,但是可以出现多个null

列及约束只要在列的定义后加上 UNIQUE

多列组合建立

[constraint 约束名]约束定义

 

也可以在修改表节奏时使用 add关键字来增加唯一约束

add uniquexxx

还可以在修改表时使用modify关键字

modify xx varchar2(5) unique

 

3.PRIMARY KEY 主键约束相当于非空约束和唯一约束 每一个表里只能有一个主键 但这个主键约束可以由多个字段建立而成

建立主键约束时,既可以使用列级约束,也可以使用表级约束,如果多个字段组合使用则只能使用表级约束

1.定义列后面加primary key

2.constraint 别名 primary keyxx

3.表级 primary keyxx ,xxx

删除

drop primary key

如果需要指定表增加主键约束 既可以通过modify 也可以通过add

 

FOREIGN KEY

外键约束主要用于保证一个或两个数据表之间的参照完整性,外键是构建与一个表的两个字段或者两个表两个字段之间的参照关系。 从表外键列的值必须在主表被参照列的值的范围之内,或者为空

主表的类被从表记录参照时,主表记录不允许被删除,必须先把从表里的参照记录的所有记录全部删除,才可以删除主表的该记录 或者删除主表记录时级联删除从表中的所有参照该记录的从表记录

 

从表外键参照只能是主表列主键列或者唯一键列 同一个表可以有多个外键

 

建立外键约束时,MYSQL也会为该列建立索引

 

外键约束通常用于定义两个实体之间的一对一 或者一对多关联关系

对于一对多关系通常在多的一段增加外键列

 

1.采用列级约束语法建立外键约束直接使用 reference关键字

2.表级 foreign key (xx) reference 主表(xxx

3.如果需要显示指定外键约束的名字 可以使用constraint来指定名字

constraint foreign key (xx) reference 主表(xxx

 

删除

drop foreign key xxx

 

5 check 约束

在定义列后面增加check(逻辑表达式)即可

 

13.2.6 索引

索引是存放在模式中的一个数据库对象,虽然索引总是从属于数据包,但它也和数据库一样属于数据库对象。创建索引的唯一作用就是加速对表的查询,索引通过使用快速访路径访问方法来快速定位数据

索引作为数据库对象,在数据字典中独立存放,但不能独立存在,必须属于某一个表

 

创建索引有两种方式

自动 当在表上定义 主键约束 唯一约束和外键约束时,系统会为该数据列自动创建对应的索引

手动 用户通过create index ... 来创建

 

删除索引也有两种方法

自动 数据表被删除时,该表索引也会被自动删除

手动 用户可以通过 drop index ...语句来删除数据表上的指定索引

索引的缺点

1. 需要一定的系统开销

2. 储存索引信息需要一定的磁盘空间

 

13.2.7 视图

试图看上去非常想一个数据表,但它不是数据表,因此它并不存储数据,视图只是一个多个数据表中数据的逻辑显示

使用视图的好处

1.可以限制对数据库的访问

2.可以使复杂的查询变的简单

3.提供了数据的独立性

4.提供了相对相同数据的不同显示

 

因为视图只是数据表中的数据逻辑显示---也就是一个查询结果,所以创建视图就是建立视图名和查询语句的关联

create or replace view

as

subquery

 

视图的本质 其实就是一条被命名的SQL查询语句

 

大部分数据库都采用with check option 来强制不允就该视图的数据,但oracle采用 with read only

删除视图

drop view

 

13.2.8 DML  语句语法

DDL 操作数据库对象不同,DML主要操作数据表里的数据,使用DML可以完成三个任务

1.插入新数据

2.修改已有数据

3.删除不需要的数据

DML 语句由insert into update delete from 三个命令组成

 

1.insert into语句

用于向指定数据表中插入记录,对于标准的SQL语句而言,每次只能插入一条记录

insert into table_name[column ,[column...])]

values (value[,value]);

如果省略了表名后面括号里所有需要插入的列名,默认将插入所有列的值

 

外键列里的值必须是被参照列里的值,所以想从表中插入记录之前,通常应该先向主表中插入记录

带子查询的插入语句甚至不要求查询数据源的表和插入数据的目的表示同一张表 只要求选择出来的列和和插入的列个数相等,数据类型匹配

 

2  update 语句

update语句用于修改数据表的记录,每次可以修改多条记录,通过使用where自己限定修改哪些记录

update table_name

set columnl = values ....

[where condition];

可以修改一个列也可以修改多个列

 

3. delete from 语句

delete from 语句用于删除指定数据表的记录,使用delete form语句删除时不需要指定列名,因为总是整行的删

可以通过where子句限定 删除满足的条件

当主标记录别从表标记是 主标记录不能被删除

1. 只有先将参照表记录的所有记录全部删除后,才能删除主表记录

2. 定义外键约束时定义了主表记录之间的级联删除 on delete cascade 或者使用 on delete set null 用于指定当主标记录被删除时,从表集合把外键列的值设为 null

 

13.2.9 单表查询

select 语句的功能就是查询数据,select语句不仅可以单表查询,还可以多表查询

当使用select语句进行查询的时候,还可以在select语句中 使用算术运算符 使用算术运算表达式 规则如下

1. 对数组类型数据列、变量、常量可以使用算术运算符(+ * /)创建表达式

2. 对日期类型数据列 变量 常量可以使用部分算术运算符(+ —)

3. 运算符不仅可以在列和常量之间进行运算,也可以在两列之间进行运算

对于MySQL 如果算术表达式中使用了null 将会导致整个算术表达式的返回值都为nullu

 

别名紧跟数据列 中间以空格隔开 或者使用 as 关键字隔开

 

如果列别名中使用特殊字符(如空格)或者强制大小写 都可以使用别名加双引号(“ ”)实现

 

如果需要选择多个列,并未多个列起别名,则列与列之间以逗号隔开,但列和列别名之间以空格隔开

 

fual 虚表 它没有任何意义,仅仅相当于from后的占位符。

使用distinct 关键字从查询结果中清楚重复行。

select distinct xx, xx from

SQL中比较运算法不仅可以比较数值之间的大小 还可以比较 日期 字符串

SQL判断两个值是否相等的比较运算符是单等号, 判断不相等的运算法是<>

SQL中的赋值运算法符不是等号,而是 :=

like 表示模糊查询 SQL还提供了两个通配符下划线(_ ,表示代表任意一个字符)(% ,代表任意多个字符) 转移字符 (\\)或者escape

 

is null 用于判断某些值是否为空 判断是否为空不要用 = null  因为 null = null 返回null

 

如果where 子句后有多个条件需要组合,SQL提供了and or

优先级关系  所有比较运算符 > not > and > or

 

order by

执行查询后查询结果默认按插入顺序排列,如果需要改变查询结果按某一列的值的大小进行排序,则可以使用order by 子句

order by column_name [desc],...

默认是升序排列

 

13.2.10 数据库函数

数据库函数一般都可以有多个或一个输入 但只有一个值作为返回值 数据库函数

可以出现在sql语句中的任何位置,通常出现在where语句中

数据库函数分为

单行函数

多行函数(也被称为聚集函数 、分组函数)

单行函数的特点

1.单行函数可以是变量、常量或数据列 可以接受多个参数但只能有一个返回值

2.单行函数会对单行独立起作用

3.单行函数可以改变参数的数据类型

 

case when

MySQL提供了一个case函数 该函数式一个流程控制函数,case函数有两种用法

1. case value

  when compare_value1 then result 1

  when compare_value2 then result 2

  ...

  else result

  end

2

case

when condition1  then result1

when condition2  then result2

...

else result

end

不推荐在java程序中使用特定的数据库函数 因为这将会导致程序代码与特定的数据库耦合,如果把程序移植到其他数据库中可能需要修改SQL语句

13.2.11 分组和组函数

distinct * 不能同时使用

在默认情况下组函数会把所有记录当成一组,为了对记录进行显示分组,可以在select语句后使用group by 子句后通常跟一个或多个列名,表明查询结果根据一列或多列进行分组--当一列或多列的组合的组完全相等,系统会把这些记录当成一组

 如果查询列表中使用了组函数,或者select语句中出现了group by 分组子句,则要求出现在select列表中的字段,要么使用组函数包起来,要么必须出现在groupby 子句中

 

having子句 如果需要对分组进行过滤,则应该使用having子句后面也是一个条件表达式,只有满足该条件表示式分组才能回选出来

where having的区别

1. where 子句中不能过滤组只能过滤行  having 可以过滤组

2. 不能在where子句中使用组函数  having 可以

 

13.2.12 多表连接查询

多表连接查询有两种规范

SQL 92 规范支持

1. 等值连接

2. 非等值连接

3. 外接连

4. 广义笛卡尔积

 

SQL 99 规范支持

1. 交叉连接

2. 自然连接

3. 使用using子句的连接

4. 使用on子句的连接

5. 全部连接或者左 右外连接

 

1 SQL 92连接查询

sql 92 的多表连接比较简单,这种语法把多个数据表都放在from之后,多个表之间以逗号隔开,连接条件放在where之后,与查询条件之间用and逻辑运算法连接

如果连接条件要求两列值相等,则称为等值连接 不相等则称为非等值连接

如果没有任何连接条件 则称为广义笛卡尔积

 

外连接 就是外连接符所在的表中增加一个“万能行”,这行的记录都是null 而且该行可以与另一个表中所有不瞒住条件的记录匹配,通过这种方式就可以把另一个表中的所有记录选出来

 

自连接 本质就是把一个表当两个表使用(当一个表中的不同记录之间存在主、外 键约束)

 

2 SQL 99连接查询

99的连接查询可读性更强 ---查询用的多个数据表显示使用 xxx join 连接 而不是直接依次排列在from之后 from只需要放一个数据表;连接条件不在放where之后 而是提供了专门的连接条件子句

 

交叉连接(cross join) 效果就是sql 92 中的广义笛卡尔积 所有无需任何条件

 

自然连接 (natural join) 自然连接 表面上看起来也无需指定外连接条件 但自然连接时有连接条件的 自然连接会以两个表中同名列作为连接条件

如果两个表中没有相同列名 则自然连接和交叉连接效果相同

 

using 子句连接 using 子句连接可用指定一列或多列 ,用于显示支出两个表中的同名列作为连接条件(假如两个表中有超过一个同名列使用using 子句可用显示指定那些同名列做连接条件)使用条件(必须是两个表的同名列)

 

on 子句连接 (最常用的连接方式) 连接条件放在on子句中指定 而且每个on子句只指定一个连接条件  on连接可用是等值连接也可以是非等值连接

 

左右全外连接 这三种连接分别使用left [outer] join  right [outer] join  full [outer] join

这三种连接一样通过on 子句来指定 既可以指定等值连接也可以指定非等值连接

 

12.2.13 子查询

子查询就是指定查询语句中嵌套另一个查询,字查询可以支持多层嵌套查询,对于一个普通查询而言 子查询可以出现在两个位置

1. 出现在from语句后面被当成数据表(行内视图)临时视图

2. 出现在where条件后作为过滤条件的值

 

使用子查询需要注意如下几点

1. 子查询要用括号括起来

2. 把子查询当成数据表时(from后),可以给子查询起别名,尤其是在作为前缀来限定数据列时

3. 把子查询当成过滤条件时,将子查询放在比较运算法的右边

4. 把子查询当成过滤条件时,单行子查询使用单行运算符多行子查询使用多行运算符

把子查询当成where条件中的值,如果子查询返回单行、单行值,则被当成一个值使用 可以使用比较运算符

如果子查询返回多个值,则需要使用 in any all 等关键字

 

13.2.14 集合运算

select 语句查询的结果是一个包含多条数据的结果集,类似于数学里的集合,可以进行交(intersect) 并(union) 和差(minus)运算

为了对两个结果集进行集合运算,这两个结果集可能需要满足如下条件

1.两个结果集所包含的数据列的数量必须相等

2.两个结果集所包含的数据列的数据类型也必须一一对应

 

1. union 运算

select 语句 union select 语句

 

2. minus 运算(MySQL不支持)

select 语句 minus select 语句

 

3. intersect 运算(MySQL不支持)

select 语句intersect select 语句

 

13.3 JDBC的经典用法

13.3.1 jdbc 4.2 常用接口

DriverManager 用于管理JDBC驱动的服务类,主要是用于获取Connection对象

Connection 代表数据库连接对象,每个Connection代表一个物理连接会话,要想访问数据库必须先获得数据库连接对象

Statement 用于执行sql语句的工具接口,返回查询到的结果集 只有获得Statement才能执行sql语句

PreparedStatement 预编译的Statement对象

ResultSet 结果集对象,该对象包含访问查询结果的方法,ResultSet可以通过列索引引用或者列数据

13.3.2 JDBC 编程步骤

1.加载数据库驱动,通常使用Class类的forName()静态方法来加载驱动,加载驱动时并不是真正使用数据库驱动类,只是使用数据库驱动类名的字符串而已

Class.forName(“driverClass”);

 

2.通过DriverManager获取数据库连接DriverManager提供了如下的方法

DriverManager.getConnection(String url ,String user ,String pass);

当使用DriverManager获取数据库连接时,通常需要传入三个参数 数据库URL 登录数据库的用户名和密码

3 通过Connection对象创建Statement 对象

 

4 使用Statement执行sql语句

 

5 操作结果集  如果执行的sql语句时查询语句,执行结果将返回一个ResultSet对象

 

6 回收数据库资源

 

13.4 执行SQL语句的方法

13.4.1 java 8 executeLargeUpdate方法执行DDL DML语句

13.4.3 使用PreparedStatement执行SQL

对于两条sql语句而言,他们的结构基本相似,只是执行插入时插入的值不同而已,对于这种情况 可以使用占位符 (?)

使用PreparedStatement可以提高编程效率,还不用拼接字符串

 

PreparedStatementparedStatement多了如下3个好处

1.PreParedStatement 预编译SQL语句,性能更好

2.PreParedStatement 无需 拼接 SQL语句,编程更简单

3.PreParedStatement 可以防止SQL注入

 

使用PreParedStatement 执行带占位符参数的SQL语句时,SQL语句中的占位符参数只能代替普通值,不要使用占位符参数替代表名,列名等数据库对象,更不要使用占位符代替SQL中的insert 等关键字

 

13.4.4 使用CallableStatement 调用存储过程

delimiter //  使用双斜杠表示结束符

通过Connection接口的prepareCall()方法来创建CallableStatement对象表示

 

13.5 管理结果集

jdbc使用ResultSet来封装执行查询得到的结果,然后通过移动ResultSet的记录指针来取出结果集的内容,除此之外 JDBC还运行通过ResultSet的记录指针来取出结果集的内容

13.5.1 可滚动、可更新的结果集

可以使用absolute() previous() afterLast()等方法只有移动指针记录的ResultSet被称为可滚动的结果集

以默认形式打开的ResultSet是不可更新的,如果希望创建可更新的ResultSet,则必须在创建StatementPreparedStatement 是传入额外的参数

可更新的结果集还需要满足如下两个条件

1.所有数据都应该来自一个表

2.选出的数据集必须包含主列键

 

13.5.2 处理Blob类型数据

BlobBinary Long Object ,二进制长对象)通常适合用于存储大文件,典型的Blob内容是一张图片或者一个声音文件,

如果需要将图片插入数据库,显然不能直接通过数据库需要使用PreparedStatement 该对象有一个关键的问题---Blob常量无法表示,所以将Blob数据插入数据库需要使用PreparedStatement  使用setBinaryStreamint parameterIndex InputStrem X)从而将Blob数据保存到数据库中

13.5.3 使用ResultSetMetaData 分析结果集

当执行SQL查询后可以通过移动记录指针来遍历ResultSet的每条记录,但程序可能不清楚该ResultSet包含哪些数据以及每个数据类型的数据类型,那么可以通过ResultSetMETADate来获取股关于ResultSet的描述信息

MetaData 表示元数据,即描述其他数据的数据

 

13.6 java 7 RowSet 1.1

RowSet 接口继承了ResultSet接口,RowSet接口下包含RowSet CachedRowSet FilterRowSet  WebRowSet 常用的子接口

除了RowSet 接口需要保持与数据库的连接之外,其余的都是离线的RowSet,无需保持与数据库的连接 (离线是直接从内存中读取)

 

ResultSet相比,RowSet默认是可滚动,可更新、可序列化的结果集

 

13.6.2 离线RowSet

在使用ResultSet的时代,程序查询得到ResultSet之后必须立即读取或处理对应的记录,否则一旦Connection关闭,再去通过ResultSet读取记录就会引发异常

当应用程序在数据访问层查询得到ResultSet之后,对ResultSet有两种常见的处理方法

1. 使用迭代访问 ResultSet里的记录,并将这些记录转换成 java Bean 在将多个Java 封装成一个List 集合,也就是ResultSet java bean 集合,然后将java bean 传入视图层(比较安全,但比较繁琐)

 

2. 直接将ResultSet传到视图显示层--这要求当视图显示层显示数据时,底层一直处于打开状态(需要Connection一直处于打开状态,不仅不安全,而且对程序性能影响较大)

 

通过使用离线RowSet可以解决问题,离线RowSet 会直接将底层数据读入内存中,封装成RowSet对象,为RowSet对象则完全可以当成java bean 来使用

 

13.6.3 离线RowSet的查询分页

由于CachedRowSet 会将数据记录直接装载到内存中,在极端情况下可能导致内存溢出

为了解决该问题,CachedRowSet提供了分页查询功能,所谓分页就是一次只装在ResultSet里的几条记录

 

13.7 事务处理

13.7.1 事务的概念和MySQL事务支持

事务由一步或者多步数据库操作系列组成的逻辑执行单元,这系列操作要么全部都执行,要么全部都失败。程序和事务是两个不同的概念。 一般而言 一段程序可以包含多个事务

 

事务具备4个特性 也称为ACID

1. 原子性(Atomicity)事务是应用中最小的执行单位 不能在分

2. 一致性(Consistency) 事务执行的结果,要么都成功要么都失败

3. 隔离型(Isolation)各个事务的执行互补干扰,任意一个内部操作对其他并发的事务都有隔离性

4. 持续性(Durability)一旦事务提交,对数据做出的改变都是永久的

 

DDL DCL 语句都会造成事务立即被提交

事务提交有两种方法

1.显示提交 commit

2.自动提交 执行 DDL  DCL 语句都会导致事务立即执行

 

事务回归有两种方式

1. 显示回滚rollback

2. 自动回滚 系统错误或者强制退出

13.7.2 JDBC的事务支持

JDBC的事务支持由Connection提供,Connection默认打开自动提交,即关闭事务,在这种情况下每条SQL语句一旦执行成功将就会被提交到数据库,永久生效

Connection setAutoCommit()方法来关闭自动提交

 

13.7.3 java 8 增强的批量更新

使用批量更新时,多条SQL语句将被作为一批操作被同时收集,并同时提交

先创建一个Statement对象

然后利用该对象的addBatch()方法将多条SQL语句同时收集起来

 

13.8 分析数据库信息

13.8.1使用DatebaseMetaData 分析数据库信息

JDBC提供了DatebaseMetaData来封装数据库连接对应的数据库信息,通过Connection提供的getMetaData()方法就可以获取对应的DatebaseMetaData对象

许多DatebaseMetaData方法一ResultSet对象的形式返回查询信息

 

13.8.2 使用系统表分析数据库信息

如果已经确定应用程序所使用的数据库系统,则可以通过数据库系统表来分析数据库信息,用户只能查,但是不能修改

 

13.9 数据库连接池

数据库连接池 常用参数

1. 数据库的初始连接数

2. 连接池的最大连接数

3. 连接池的最小连接数

4. 连接池每次增加的连接数

 

13.9.1DBCP 数据源

DBCP连接池依赖该组织下的另一个开源系统,common-pool 如果需要使用该连接池实现,则应该在系统中增加如下的2jar

Commons-dbcp.jar

commous-pool.jar

数据源和数据连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可

13.9.2 C3P0 数据源

相比之下 C3P0更胜一筹,hibernate就是推荐使用该连接池,C3P0不仅可以自动清理不在使用的Connection 还可以自动清理 StatementResultSet 

以上是关于jdbc编程基础-1的主要内容,如果未能解决你的问题,请参考以下文章

Java基础教程:JDBC编程

JDBC编程JAVA

JDBC基础01

JDBC基础

MySQL 数据库与JDBC编程

JDBC基础学习