【12-JDBC编程】

JDBC编程


JDBC概述

  •通过使用JDBC API,Java程序可以非常方便地操作各种主流数据库,这是使Java语言的巨大

魅力所在。而且由于Java语言的跨平台特性,所以使用JDBC API所编写的程序不仅可以实现跨数据

库,还可以跨平台,具有非常优秀的可移植性。

 

  •程序使用JDBC API以统一的方式来连接不同的数据库,然后通过Statement对象来执行标准

SQL语句,并可以获得SQL语句访问数据库的结果。因此掌握标准SQL语句是学习JDBC编程的基础,

本章将会简要介绍关系数据库理论基础,并以MySQL数据库为例来讲解标准SQL语句的语法细节。包

括基本查询语句,多表连接查询和子查询等。


 

 JDBC驱动示意

•为了JDBC程序可以跨平台,则需要不同数据库厂商提供相应的驱动,下图显示了JDBC驱动的示意

图。

 


JDBC驱动程序类型 

•第一种JDBC驱动:称为JDBC–ODBC桥,这种驱动是最早实现的JDBC驱动程序,主要目的是为了

快速推广JDBC。这种驱动程序将JDBC API映射到ODBC API。JDBC-ODBC也需要驱动,这种驱

动由Sun公司提供实现。

 

•第二种JDBC驱动:直接将JDBC API映射成数据库特定的客户端API。这种驱动程序包含特定数据

库的本地代码,用于访问特定数据库的客户端。

 

•第三种JDBC驱动:支持三层结构的JDBC访问方式。主要用于Applet阶段,通过Applet访问数据

库。

 

•第四种JDBC驱动:是纯Java的,直接与数据库实例交互。这种驱动是智能的,它知道数据库使用的

底层协议。这种驱动是目前最流行的JDBC驱动。


 

 安装MySQL

•(1)下载MySQL安装文件

•(2)开始安装MySQL后,在出现的对话框中单击“Next”按钮。

•(3)单击对话框的“Next”按钮,将出现选择安装组件和安装路径的对话框。

•(4)单击对话框中的“Next”按钮,将可开始安装MySQL数据库系统。安装成功后,系统还要求配置MySQL数据库。

•(5)配置数据库时注意选择合适的字符集,并设置密码。


 

 MySQL的常见命令

•show databases;

•drop database 数据库名;

•use 数据库名

•show tables;

•desc 表名


MySQL的两种存储机制

•MyISAM:这是MySQL早期默认的存储机制,对事务支持不够好。

 

•InnoDB:InnoDB提供事务安全的存储机制。InnoDB通过建立行级锁来保证事务完整性,并以

Oracle风格的共享锁来处理Select语句。 系统默认启动InnoDB机制,如果不想使用 InnoDB表,

可以使用skip-innodb 选项。


 

 SQL语句 

•SQL的全称是Structured Query Language,也就是结构化查询语言。SQL是操作和检索关系型

数据库的标准语言,标准SQL语句可用于操作任何关系数据库。

 

•使用SQL语句,程序员和数据库管理员(DBA)可以完成如下的任务:

–在数据库中检索需要的信息。

–对数据库的信息进行更新。

–改变数据库的结构。

–更改系统的安全设置。

–增加用户对数据库或表的许可权限。


 

 SQL语句分类

•查询语句:主要由于select关键字完成,查询语句是SQL语句中最复杂,功能也最丰富的语句。

•DML语句(Data Manipulation Language,即数据操作语言):主要由  insertupdatedelete三个关键字完成。

•DDL语句(Data Definition Language,即使数据定义语言):主要由create、alter、drop和truncate四个关键字完成。

•DCL语句(Data Control Language,即使数据控制语言):主要由grantrevoke两个关键字完成。

•事务控制语句:主要由commitrollbacksavepoint三个关键字完成。


 

 DDL语句 

•DDL语句是操作数据库对象的语句,包括

–创建(create)

–删除(drop)

–修改(alter)数据库对象。 


 

 数据库对象

对象名称

对应关键字

描述

table

表是存储数据的逻辑单元,以行和列的形式存在;列就是字段,行就是记录。

数据字典

 

就是系统表,存放数据库相关信息的表。系统表里的数据通常由数据库系统维护。程序员通常不应该手动修改系统表及内部数据,程序员只可查看系统表的数据。

约束

constraint

执行数据校验的规则,用于保证了数据完整性的规则。

视图

view

一个或者多个数据表里数据的逻辑显示。视图并不存储数据。

索引

index

用于提高查询的性能,相当于书的目录。

函数

function

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

存储过程

procedure

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

触发器

trigger

相当于一个事件监听器,当数据库发生特定事件后,触发器被触发,完成响应的处理。


创建表的语法

create table [模式名.]表名
(
    -- 可以有多个列定义
    columnName1 datatype [default expr] , 
    …
)

修改表(增加列)的语法

alter table 表名
add 
(
    -- 可以有多个列定义
    column_name1 datatype [default expr] , 
    …
);

 修改表(修改列)的语法

alter table 表名
modify column_name datatype [default expr] [first|after col_name];

修改表(删除列)的语法

•alter table 表名

•drop column_name


 

 删除表的语法

•drop table 表名;


约束

•大部分数据库支持下面五类完整性约束:

–NOT NULL:非空约束,指定某列不能为空。

–UNIQUE:唯一约束,指定某列或者几列组合不能重复。

–PRIMARY KEY:主键,指定该列的值可以唯一地表示该条记录。

–FOREIGN KEY:外键,指定该行记录从属于主表中的一条记录,主要用于保证参照完整性。

–CHECK:检查,指定一个布尔表达式,用于指定对应列的值必须满足该表达式。


 

 索引

•索引是存放在模式(schema)中的一个数据库对象,虽然索引总是从属于数据表,但它也和数据表

一样,属于数据库对象。创建索引唯一的作用就是加速对表的查询,索引通过使用快速路径访问方法来

快速定位数据,从而减少了磁盘的I/O。

 

•创建索引有两种方式:

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

–手动:用户可以手动创建索引来加速查询。

 

•删除索引也有两种方式:

–自动:数据表被删除时,该表上的索引自动被删除。

–手动:用户可以手动删除指定数据表上的指定索引。


 

 视图

•视图看上去非常像一个数据表,但它不是数据表,因为它并不能存储数据。视图只是一个或多个数据表中数据的逻辑显示。使用视图有如下几个好处:

–可以限制对数据的访问。

–可以使复杂的查询变得简单。

–提供了数据的独立性。

–提供了对相同数据的不同显示。


 

 创建视图的语法

•create or replace view 视图名

•as

•subquery


 

 DML语句

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

–插入新数据。

–修改已有数据。

–删除不需要的数据。


 

 insert into

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

insert into命令的语法格式如下:

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

–values(value [, value...]);


 

 update语句

•update语句用于修改数据库记录,每次修改可以修改多条记录,可通过使用where子句限定修改哪些记录。where子句是一个条件表达式,该条件表达式类似于Java编程语言的if,只有符合该条件的记录才会被修改。如果没有where子句意味着where子句的表达式值总是true,即该表的所有记录都会被修改。update语句的语法格式如下:

–update table_name

–set column1= value1[, column2 = value2] …

–[WHERE condition];


 

 delete from语句

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

•delete from删除可以一次删除多行,删除哪些行采用where子句限定,只删除满足where条件的记录。没有where子句将会把表里的全部记录删除。

•delete from语句的语法格式如下:

–delete from table_name

–[WHERE condition];


 

 SELECT语句

•select语句功能就是查询数据,select语句也是SQL语句中功能最丰富的语句,select语句不仅可以执行单表查询,还可以执行多表连接查询,还可以进行子查询,select语句用于从一个或多个数据表中选出特定行、特定列的交集。

•最简单的select语句的语法格式如下:

–select column1, column2 ...

–from 数据源

–[where condition]


 

 SELECT语句的规则

•当使用select语句进行查询时,还可以在select语句中使用算术运算符(+  -  *  /),从而形成算术表达式,使用算数表达式的规则如下:

–对数值型数据列、变量、常量可以使用算数操作符(+  -  *  /)创建表达式。

–对日期型数据列、变量、常量可以使用部分算数操作符创建表达式 (+  -),两个日期之间可以进行减法运算,日期和数值之间可进行加、减运算。

–运算符不仅可以在列和常量、变量之间进行运算,也可以在两列之间进行运算。


 

 特殊比较运算符

 


 数据库函数

•每个数据库都会在标准SQL基础上扩展一些函数,这些函数用于进行数据处理或复杂计算,

•根据函数对多行数据的处理方式,函数被分为单行函数和多行函数,单行函数对每行输入值单独计算,每行得到一个计算结果返回给用户。多行函数对多行输入值整体计算,最后只会得到一个结果。单行函数和的多行函数的示意如图所示:


组函数

•组函数也就是前面提到多行函数,组函数将一组记录作为整体计算,每一组记录返回一个结果,而不是每一条记录返回一个结果。常用的组函数有如下5个:

avg([distinct|all]expr):计算多行expr的平均值,其中expr可以是变量、常量或数据列,但其数据类型必须数值型。还可以在变量、列前使用distinct或all关键字,如果使用distinct表明不计算重复值;all用和不用的效果完全一样,表明需要计算重复值。

count({ *|[distinct|all]expr}):计算多行expr的平均值,其中expr可以是变量、常量或数据列,其数据类型可以是任意类型。用星号(*)表示统计该表内的记录行数。其中distinct表示不计算重复值。

max([distinct]expr):计算多行expr的平均值,其中expr可以是变量、常量或数据列,其数据类型可以是任意类型。其中distinct表示不计算重复值。

min([distinct]expr):计算多行expr的平均值,其中expr可以是变量、常量或数据列,其数据类型可以是任意类型。其中distinct表示不计算重复值。

sum([distinct|all]expr):计算多行expr的总和,其中expr可以是变量、常量或数据列,但其数据类型必须数值型。其中distinct表示不计算重复值。


 

 多表连接查询 

•多表连接查询有两种规范,较早的SQL92规范中支持如下几种多表连接查询:

–等值连接。

–非等值连接。

–外连接。

–广义笛卡尔积。


 

 SQL99的多表连接查询

•SQL99规则提供了可读性更好的多表连接语法,并提供更多类型的连接查询,SQL99支持如下几种多表连接查询:

–交叉连接。

–自然连接。

–使用using子句的连接。

–使用on子句的连接。

–全外连接或者左右外连接。 


 

 子查询

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

–出现在from语句后当成数据表,这种用法也被称为行内视图,因为该子查询的实质就是一个临时视图。

–出现在where条件后作为过滤条件的值。


 

 使用子查询的注意点

•使用子查询时有如下几个注意点:

–子查询要用括号括起来。

–子查询当成数据表时,可以为该子查询起别名,尤其是要作为前缀来限定数据列时,必须给子查询起别名。

–子查询当过滤条件时,将子查询放在比较运算符的右边,这样可以增强查询的可读性。

–子查询当过滤条件时,单行子查询使用单行运算符,多行子查询使用多行运算符。


 

 JDBC常用接口和类 

•DriverManager

•Connection

•Statement

•PreparedStatement

•ResultSet


JDBC编程步骤 

•(1)加载数据库驱动。

•(2)通过DriverManager获取数据库连接。

•(3)通过Connection对象创建Statement对象。

•(4)使用Statement执行SQL语句。所有Statement都有如下三个方法来执行SQL语句。

•(5)操作结果集。如果执行的SQL语句是查询语句,执行结果将返回一个ResultSet对象,该对象里保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象来取出查询结果。 


JDBC执行SQL语句的方式

•使用executeUpdate执行DDL和DML语句

•使用execute方法执行SQL语句

•使用executeQuery方法执行查询语句 


PreparedStatement

•JDBC提供了PreparedStatement接口,它是Statement接口的子接口,它可以预编译SQL语句,预编译后的SQL语句被存储在PreparedStatement对象中。然后可以使用该对象多次高效地执行该语句。简而言之,使用PreparedStatement比使用Statement的效率要高。

•使用PreparedStatement比使用Statement多了如下三个好处:

–PreparedStatement预编译SQL语句,性能更好。

–PreparedStatment无需“拼接”SQL语句,编程更简单。

–PreparedStatement可以防止SQL注入,安全性更好。


 

 CallableStatment

•调用存储过程使用CallableStatement,可以通过Connection的prepareCall方法来创建

CallableStatement对象,创建该对象时需要传入调用存储过程的SQL语句,调用存储过程的SQL语

句总是这种格式:{call 过程名(?,?,?...)},其中的问号作为存储过程参数的占位符。

 

•存储过程的参数既有传入参数,也有传出参数。所谓传入参数就是Java程序必须为这些参数传入

值,那么可以通过CallableStatement的setXxx方法为传入参数设置值;所谓传出参数就是Java程

序可以通过该参数获取存储过程里的值,那么CallableStatement需要调用

registerOutParameter方法来注册该参数。 


 

 可滚动、可更新的结果集 

•以默认方式打开的ResultSet是不可更新的,如果希望创建可更新的ResultSet,必须在创建

Statement或PreparedStatement时传入额外的参数。Connection在创建Statement或

PreparedStatement时还可额外传入两个参数:

 

•resultSetType:控制ResultSet的类型,该参数可以是如下三个值:

–ResultSet.TYPE_FORWARD_ONLY:该常量控制记录指针只能向前移动。这是JDK1.4以前的默认值。

–ResultSet.TYPE_SCROLL_INSENSITIVE:该常量控制记录指针可以自由移动(可滚动结果集),但底层数据的改变不会影响ResultSet的内容。

–ResultSet.TYPE_SCROLL_SENSITIVE:该常量控制记录指针可以自由移动(可滚动结果集),而且底层数据的改变会影响ResultSet的内容。

•resultSetConcurrency:控制ResultSet的并发类型,该参数可以接受如下两个值:

–ResultSet.CONCUR_READ_ONLY:该常量指示ResultSet是只读的并发模式(默认)。

–ResultSet.CONCUR_UPDATABLE:该常量指示ResultSet是可更新的并发模式。 


 

 处理Blob类型数据 

•所以将Blob数据插入数据库需要使用PreparedStatement,该对象有一个方法:

setBinaryStream(int parameterIndex, InputStream x),该方法可以为指定参数传入二进制

输入流,从而可以实现将Blob数据保存到数据库的功能。

 

•当我们需要从ResultSet里取出Blob数据时,可以调用ResultSet的getBlob(int

columnIndex)方法,该方法将返回一个Blob对象,Blob对象提供了getBinaryStream方法来获

取该Blob数据的输入流,也可使用Blob对象提供的getBytes方法直接取出该Blob对象封装的二进制

数据。


 

 使用ResultSetMetaData

•ResultSet里包含一个getMetaData()方法,该方法返回该ResultSet对应的

ResultSetMetaData对象。一旦获得了ResultSetMetaData对象,就可通过

ResultSetMetaData提供的大量的方法来返回ResultSet的描述信息,常用的方法有如下三个:

 

–int getColumnCount():返回该ResultSet的列数量。

–String getColumnName(int column):返回指定索引的列名。

–int getColumnType(int column):返回指定索引的列类型。


 

 事务

•事务是由一步或几步数据库操作序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。程序和事务是两个不同的概念。一般而言:一段程序中可能包含多个事务。

•事务具备四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、和持续性(Durability)。这四个特性也简称为ACID性。

原子性(Atomicity)

一致性(Consistency)

隔离性(Isolation)

持续性(Durability)


 

 事务的组成

•数据库的事务由下列语句组成:

–一组DML语句,经过这组DML修改后数据将保持较好的一致性。

–一个 DDL 语句。

–一个 DCL 语句。

•DDL和DCL语句最多只能有一个,因为DDL和DCL语句都会导致事务立即提交。


 

 事务的结束

•当事务所包含的全部数据库操作都成功执行后,应该提交(commit)事务,使这些修改永久生效。事务提交有两种方式:显式提交和自动提交。

–显式提交:使用commit

–自动提交:执行DDL或DCL,或者程序正常退出。

•当事务所包含的任意一个数据库操作执行失败后,应该回滚(rollback)事务,使该事务中所作的修改全部失效。事务回滚有两种方式:显式回滚和自动回滚。

–显式回滚:使用rollback

–自动回滚:系统错误或者强行退出。


 

 JDBC的事务支持 

•Connection的setAutoCommit方法来关闭自动提交,开启事务,如下SQL语句所示:

conn.setAutoCommit(false);

•程序可以调用Connection的commit方法来提交事务,如下代码所示:

conn.commit();

•如果任意一条SQL语句执行失败,我们应该用Connection的rollback来回滚事务,如下代码所示:

conn.rollback();


 

 事务的中间点

•Connection也提供了设置中间点的方法:setSavepoint,Connection提供了两个方法来设置中间点:

–Savepoint setSavepoint():在当前事务中创建一个未命名的中间点),并返回代表该中间点的Savepoint对象。

–Savepoint setSavepoint(String name):在当前事务中创建一个具有指定名称的中间点,并返回代表该中间点的Savepoint对象。

•通常来说,设置中间点时没有太大的必要指定名称,因为Connection回滚到指定中间点时,并不是

根据名字回滚的,而是根据中间点对象回滚的。Connection提供了rollback(Savepoint

savepoint)方法来回滚到指定中间点。


 

 批量更新

•JDBC还提供了一个批量更新的功能,使用批量更新时,多条SQL语句将会被作为一批操作被同时收

集、并同时提交。

 

•批量更新必须得到底层数据库的支持,可以通过调用DatabaseMetaData的

supportsBatchUpdates方法来查看底层数据库是否支持批量更新。

 

•使用批量更新也需要先创建一个Statement对象,然后利用该对象addBatch方法将多条SQL语句

同时收集起来,最后调用Statement对象的executeBatch同时执行这些SQL语句。


 

 DatabaseMetaData

•JDBC提供了DatabaseMetaData来封装数据库连接对应数据库的信息,通过Connection提供的

getMetaData()方法就可以获取到数据库对应的DatabaseMetaData对象。

 

•许多DatabaseMetaData方法以 ResultSet 对象的形式返回查询的信息,使用ResultSet的常规

方法(例如getString 和 getInt)即可从这些ResultSet对象中获取数据。如果查询的信息不可

用,则将返回一个空ResultSet对象。

 

•很多DatabaseMetaData方法都需要传入一个xxxPattern的模式字符串,这里的xxxPattern不

是正则表达式,而是SQL里的模式字符串,即用百分号(%)代表任意多个字符,使用下划线(_)代

表一个字符。通常情况下,如果把该模式字符串参数值设置为null,即表明该参数不作为过滤条件。 


 

 使用数据库系统表

•MySQL的数据库系统表使用information_schema数据库来保存,在该数据库里包含了大量系统表,常用系统表的简单介绍如下:

–tables-存放数据库里所有数据表的信息。

–schemata-存放数据库里所有数据库(与MySQL的Schema一一对应)的信息

–views-存放数据库里所有视图的信息。

–columns-存放数据库里所有列的信息。

–triggers-存放数据库里所有触发器的信息。

–routines-存放数据库里所有存储过程和函数的信息。

–key_column_usage-存放数据库里所有具有约束的键信息。

–table_constraints-存放数据库全部约束的表信息。

–statistics-存放了数据库里全部索引的信息。


 

 数据库连接池

•数据库连接池的解决方案是:当应用程序启动时,系统主动建立足够的数据库连接,并将这些连接组

成一个连接池。每次应用程序请求数据库连接时,无需重新打开连接,而是从池中取出已有的连接使

用,使用完后,不再关闭数据库连接,而是直接将该连接归还给连接池。通过使用连接池,将大大提高

程序运行效率。

•数据库连接池的常用参数有如下:

–数据库的初始连接数。

–连接池的最大连接数。

–连接池的最小连接数。

–连接池的每次增加的容量。 


 

 两种常见的开源数据源

•DBCP是Apache软件基金组织下的开源连接池实现,该连接池依赖该组织下的另一个开源系统:

common-pool。

 

•相比之下,C3P0数据源性能更胜一筹,Hibernate就推荐使用该连接池。C3P0连接池不仅可自动

清理不再使用的Connection,还可以自动清理Statement和ResultSet。C3P0连接池需要版本为

1.3以上的JRE,推荐使用1.4以上的JRE。


 

 现在贴出代码:

drop database if exists select_test;
create database select_test;
use select_test;
# 为了保证从表参照的主表存在,通常应该先建主表。
create table teacher_table
(
    # auto_increment:实际上代表所有数据库的自动编号策略,通常用作数据表的逻辑主键。
    teacher_id int auto_increment,
    teacher_name varchar(255),
    primary key(teacher_id)
);
create table student_table
(
    # 为本表建立主键约束
    student_id int auto_increment primary key,
    student_name varchar(255),
    # 指定java_teacher参照到teacher_table的teacher_id列
    java_teacher int,
    foreign key(java_teacher) references teacher_table(teacher_id)
);
insert into teacher_table
values
(null , 'Yeeku');
insert into teacher_table
values
(null , 'Leegang');
insert into teacher_table
values
(null , 'Martine');
insert into student_table
values
(null , '张三' , 1);
insert into student_table
values
(null , '张三' , 1);
insert into student_table
values
(null , '李四' , 1);
insert into student_table
values
(null , '王五' , 2);
insert into student_table
values
(null , '_王五' , 2);

insert into student_table
values
(null , null , 2);
insert into student_table
values
(null , '赵六' , null);
sql
create table user_inf
(
    user_id int primary key auto_increment,
    user_name varchar(255)
);
sql
public class ConnMySql {
    public static void main(String[] args) throws Exception {
        // 1.加载驱动,使用反射的知识,现在记住这么写。
        Class.forName("com.mysql.jdbc.Driver");
        try (
        // 2.使用DriverManager获取数据库连接,
        // 其中返回的Connection就代表了Java程序和数据库的连接
        // 不同数据库的URL写法需要查驱动文档知道,用户名、密码由DBA分配
        Connection conn = DriverManager.getConnection(
                "jdbc:mysql://127.0.0.1:3306/select_test", "root", "32147");
        // 3.使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement();
                // 4.执行SQL语句
                /*
                 * Statement有三种执行sql语句的方法: 1 execute 可执行任何SQL语句。- 返回一个boolean值,
                 * 如果执行后第一个结果是ResultSet,则返回true,否则返回false 2 executeQuery
                 * 执行Select语句 - 返回查询到的结果集 3 executeUpdate 用于执行DML语句。- 返回一个整数,
                 * 代表被SQL语句影响的记录条数
                 */
                ResultSet rs = stmt.executeQuery("select s.* , teacher_name"
                        + " from student_table s , teacher_table t"
                        + " where t.teacher_id = s.java_teacher")) {
            // ResultSet有系列的getXxx(列索引 | 列名),用于获取记录指针
            // 指向行、特定列的值,不断地使用next()将记录指针下移一行,
            // 如果移动之后记录指针依然指向有效行,则next()方法返回true。
            while (rs.next()) {
                System.out.println(rs.getInt(1) + "	" + rs.getString(2) + "	"
                        + rs.getString(3) + "	" + rs.getString(4));
            }
        }
    }
}
View Code

public class CallableStatementTest {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void callProcedure() throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 使用Connection来创建一个CallableStatment对象
                CallableStatement cstmt = conn
                        .prepareCall("{call add_pro(?,?,?)}")) {
            cstmt.setInt(1, 4);
            cstmt.setInt(2, 5);
            // 注册CallableStatement的第三个参数是int类型
            cstmt.registerOutParameter(3, Types.INTEGER);
            // 执行存储过程
            cstmt.execute();
            // 获取,并输出存储过程传出参数的值。
            System.out.println("执行结果是: " + cstmt.getInt(3));
        }
    }

    public static void main(String[] args) throws Exception {
        CallableStatementTest ct = new CallableStatementTest();
        ct.initParam("mysql.ini");
        ct.callProcedure();
    }
}
View Code
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/select_test
user=root
pass=32147
mysql.ini
public class ExecuteDDL {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void createTable(String sql) throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement()) {
            // 执行DDL,创建数据表
            stmt.executeUpdate(sql);
        }
    }

    public static void main(String[] args) throws Exception {
        ExecuteDDL ed = new ExecuteDDL();
        ed.initParam("mysql.ini");
        ed.createTable("create table jdbc_test "
                + "( jdbc_id int auto_increment primary key, "
                + "jdbc_name varchar(255), " + "jdbc_desc text);");
        System.out.println("-----建表成功-----");
    }
}
View Code
public class ExecuteDML {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public int insertData(String sql) throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement()) {
            // 执行DML,返回受影响的记录条数
            return stmt.executeUpdate(sql);
        }
    }

    public static void main(String[] args) throws Exception {
        ExecuteDML ed = new ExecuteDML();
        ed.initParam("mysql.ini");
        int result = ed.insertData("insert into jdbc_test(jdbc_name,jdbc_desc)"
                + "select s.student_name , t.teacher_name "
                + "from student_table s , teacher_table t "
                + "where s.java_teacher = t.teacher_id;");
        System.out.println("--系统中共有" + result + "条记录受影响--");
    }
}
View Code
public class ExecuteSQL {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void executeSql(String sql) throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 使用Connection来创建一个Statement对象
                Statement stmt = conn.createStatement()) {
            // 执行SQL,返回boolean值表示是否包含ResultSet
            boolean hasResultSet = stmt.execute(sql);
            // 如果执行后有ResultSet结果集
            if (hasResultSet) {
                try (
                // 获取结果集
                ResultSet rs = stmt.getResultSet()) {
                    // ResultSetMetaData是用于分析结果集的元数据接口
                    ResultSetMetaData rsmd = rs.getMetaData();
                    int columnCount = rsmd.getColumnCount();
                    // 迭代输出ResultSet对象
                    while (rs.next()) {
                        // 依次输出每列的值
                        for (int i = 0; i < columnCount; i++) {
                            System.out.print(rs.getString(i + 1) + "	");
                        }
                        System.out.print("
");
                    }
                }
            } else {
                System.out
                        .println("该SQL语句影响的记录有" + stmt.getUpdateCount() + "条");
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ExecuteSQL es = new ExecuteSQL();
        es.initParam("mysql.ini");
        System.out.println("------执行删除表的DDL语句-----");
        es.executeSql("drop table if exists my_test");
        System.out.println("------执行建表的DDL语句-----");
        es.executeSql("create table my_test"
                + "(test_id int auto_increment primary key, "
                + "test_name varchar(255))");
        System.out.println("------执行插入数据的DML语句-----");
        es.executeSql("insert into my_test(test_name) "
                + "select student_name from student_table");
        System.out.println("------执行查询数据的查询语句-----");
        es.executeSql("select * from my_test");
    }
}
View Code
public class LoginFrame {
    private final String PROP_FILE = "mysql.ini";
    private String driver;
    // url是数据库的服务地址
    private String url;
    private String user;
    private String pass;
    // 登录界面的GUI组件
    private JFrame jf = new JFrame("登录");
    private JTextField userField = new JTextField(20);
    private JTextField passField = new JTextField(20);
    private JButton loginButton = new JButton("登录");

    public void init()throws Exception
    {
        Properties connProp = new Properties();
        connProp.load(new FileInputStream(PROP_FILE));
        driver = connProp.getProperty("driver");
        url = connProp.getProperty("url");
        user = connProp.getProperty("user");
        pass = connProp.getProperty("pass");
        // 加载驱动
        Class.forName(driver);
        // 为登录按钮添加事件监听器
        loginButton.addActionListener(e -> {
            // 登录成功则显示“登录成功”
            if (validate(userField.getText(), passField.getText()))
            {
                JOptionPane.showMessageDialog(jf, "登录成功");
            }
            // 否则显示“登录失败”
            else
            {
                JOptionPane.showMessageDialog(jf, "登录失败");
            }
        });
        jf.add(userField , BorderLayout.NORTH);
        jf.add(passField);
        jf.add(loginButton , BorderLayout.SOUTH);
        jf.pack();
        jf.setVisible(true);
    }

    // private boolean validate(String userName, String userPass)
    // {
    // // 执行查询的SQL语句
    // String sql = "select * from jdbc_test "
    // + "where jdbc_name='" + userName
    // + "' and jdbc_desc='" + userPass + "'";
    // System.out.println(sql);
    // try(
    // Connection conn = DriverManager.getConnection(url , user ,pass);
    // Statement stmt = conn.createStatement();
    // ResultSet rs = stmt.executeQuery(sql))
    // {
    // // 如果查询的ResultSet里有超过一条的记录,则登录成功
    // if (rs.next())
    // {
    // return true;
    // }
    // }
    // catch(Exception e)
    // {
    // e.printStackTrace();
    // }
    // return false;
    // }

    private boolean validate(String userName, String userPass) {
        try (Connection conn = DriverManager.getConnection(url, user, pass);
                PreparedStatement pstmt = conn
                        .prepareStatement("select * from jdbc_test where jdbc_name=? and jdbc_desc=?")) {
            pstmt.setString(1, userName);
            pstmt.setString(2, userPass);
            try (ResultSet rs = pstmt.executeQuery()) {
                // 如果查询的ResultSet里有超过一条的记录,则登录成功
                if (rs.next()) {
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static void main(String[] args) throws Exception {
        new LoginFrame().init();
    }
}
View Code
public class PreparedStatementTest {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
        // 加载驱动
        Class.forName(driver);
    }

    public void insertUseStatement() throws Exception {
        long start = System.currentTimeMillis();
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement()) {
            // 需要使用100条SQL语句来插入100条记录
            for (int i = 0; i < 100; i++) {
                stmt.executeUpdate("insert into student_table values("
                        + " null ,'姓名" + i + "' , 1)");
            }
            System.out.println("使用Statement费时:"
                    + (System.currentTimeMillis() - start));
        }
    }

    public void insertUsePrepare() throws Exception {
        long start = System.currentTimeMillis();
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 使用Connection来创建一个PreparedStatement对象
                PreparedStatement pstmt = conn
                        .prepareStatement("insert into student_table values(null,?,1)"))

        {
            // 100次为PreparedStatement的参数设值,就可以插入100条记录
            for (int i = 0; i < 100; i++) {
                pstmt.setString(1, "姓名" + i);
                pstmt.executeUpdate();
            }
            System.out.println("使用PreparedStatement费时:"
                    + (System.currentTimeMillis() - start));
        }
    }

    public static void main(String[] args) throws Exception {
        PreparedStatementTest pt = new PreparedStatementTest();
        pt.initParam("mysql.ini");
        pt.insertUseStatement();
        pt.insertUsePrepare();
    }
}
View Code

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/select_test
user=root
pass=32147
mysql.ini
public class BlobTest {
    JFrame jf = new JFrame("图片管理程序");
    private static Connection conn;
    private static PreparedStatement insert;
    private static PreparedStatement query;
    private static PreparedStatement queryAll;
    // 定义一个DefaultListModel对象
    private DefaultListModel<ImageHolder> imageModel = new DefaultListModel<>();
    private JList<ImageHolder> imageList = new JList<>(imageModel);
    private JTextField filePath = new JTextField(26);
    private JButton browserBn = new JButton("...");
    private JButton uploadBn = new JButton("上传");
    private JLabel imageLabel = new JLabel();
    // 以当前路径创建文件选择器
    JFileChooser chooser = new JFileChooser(".");
    // 创建文件过滤器
    ExtensionFileFilter filter = new ExtensionFileFilter();
    static {
        try {
            Properties props = new Properties();
            props.load(new FileInputStream("mysql.ini"));
            String driver = props.getProperty("driver");
            String url = props.getProperty("url");
            String user = props.getProperty("user");
            String pass = props.getProperty("pass");
            Class.forName(driver);
            // 获取数据库连接
            conn = DriverManager.getConnection(url, user, pass);
            // 创建执行插入的PreparedStatement对象,
            // 该对象执行插入后可以返回自动生成的主键
            insert = conn.prepareStatement("insert into img_table"
                    + " values(null,?,?)", Statement.RETURN_GENERATED_KEYS);
            // 创建两个PreparedStatement对象,用于查询指定图片,查询所有图片
            query = conn.prepareStatement("select img_data from img_table"
                    + " where img_id=?");
            queryAll = conn.prepareStatement("select img_id, "
                    + " img_name from img_table");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void init()throws SQLException
    {
        // -------初始化文件选择器--------
        filter.addExtension("jpg");
        filter.addExtension("jpeg");
        filter.addExtension("gif");
        filter.addExtension("png");
        filter.setDescription("图片文件(*.jpg,*.jpeg,*.gif,*.png)");
        chooser.addChoosableFileFilter(filter);
        // 禁止“文件类型”下拉列表中显示“所有文件”选项。
        chooser.setAcceptAllFileFilterUsed(false);
        // ---------初始化程序界面---------
        fillListModel();
        filePath.setEditable(false);
        // 只能单选
        imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JPanel jp = new JPanel();
        jp.add(filePath);
        jp.add(browserBn);
        browserBn.addActionListener(event -> {
            // 显示文件对话框
            int result = chooser.showDialog(jf , "浏览图片文件上传");
            // 如果用户选择了APPROVE(赞同)按钮,即打开,保存等效按钮
            if(result == JFileChooser.APPROVE_OPTION)
            {
                filePath.setText(chooser.getSelectedFile().getPath());
            }
        });
        jp.add(uploadBn);
        uploadBn.addActionListener(avt -> {
            // 如果上传文件的文本框有内容
            if (filePath.getText().trim().length() > 0)
            {
                // 将指定文件保存到数据库
                upload(filePath.getText());
                // 清空文本框内容
                filePath.setText("");
            }
        });
        JPanel left = new JPanel();
        left.setLayout(new BorderLayout());
        left.add(new JScrollPane(imageLabel) , BorderLayout.CENTER);
        left.add(jp , BorderLayout.SOUTH);
        jf.add(left);
        imageList.setFixedCellWidth(160);
        jf.add(new JScrollPane(imageList) , BorderLayout.EAST);
        imageList.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent e)
            {
                // 如果鼠标双击
                if (e.getClickCount() >= 2)
                {
                    // 取出选中的List项
                    ImageHolder cur = (ImageHolder)imageList.
                    getSelectedValue();
                    try
                    {
                        // 显示选中项对应的Image
                        showImage(cur.getId());
                    }
                    catch (SQLException sqle)
                    {
                        sqle.printStackTrace();
                    }
                }
            }
        });
        jf.setSize(620, 400);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);
    }

    // ----------查找img_table填充ListModel----------
    public void fillListModel() throws SQLException {

        try (
        // 执行查询
        ResultSet rs = queryAll.executeQuery()) {
            // 先清除所有元素
            imageModel.clear();
            // 把查询的全部记录添加到ListModel中
            while (rs.next()) {
                imageModel.addElement(new ImageHolder(rs.getInt(1), rs
                        .getString(2)));
            }
        }
    }

    // ---------将指定图片放入数据库---------
    public void upload(String fileName) {
        // 截取文件名
        String imageName = fileName.substring(fileName.lastIndexOf('\') + 1,
                fileName.lastIndexOf('.'));
        File f = new File(fileName);
        try (InputStream is = new FileInputStream(f)) {
            // 设置图片名参数
            insert.setString(1, imageName);
            // 设置二进制流参数
            insert.setBinaryStream(2, is, (int) f.length());
            int affect = insert.executeUpdate();
            if (affect == 1) {
                // 重新更新ListModel,将会让JList显示最新的图片列表
                fillListModel();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // ---------根据图片ID来显示图片----------
    public void showImage(int id) throws SQLException {
        // 设置参数
        query.setInt(1, id);
        try (
        // 执行查询
        ResultSet rs = query.executeQuery()) {
            if (rs.next()) {
                // 取出Blob列
                Blob imgBlob = rs.getBlob(1);
                // 取出Blob列里的数据
                ImageIcon icon = new ImageIcon(imgBlob.getBytes(1L,
                        (int) imgBlob.length()));
                imageLabel.setIcon(icon);
            }
        }
    }

    public static void main(String[] args) throws SQLException {
        new BlobTest().init();
    }
}

// 创建FileFilter的子类,用以实现文件过滤功能
class ExtensionFileFilter extends FileFilter {
    private String description = "";
    private ArrayList<String> extensions = new ArrayList<>();

    // 自定义方法,用于添加文件扩展名
    public void addExtension(String extension) {
        if (!extension.startsWith(".")) {
            extension = "." + extension;
            extensions.add(extension.toLowerCase());
        }
    }

    // 用于设置该文件过滤器的描述文本
    public void setDescription(String aDescription) {
        description = aDescription;
    }

    // 继承FileFilter类必须实现的抽象方法,返回该文件过滤器的描述文本
    public String getDescription() {
        return description;
    }

    // 继承FileFilter类必须实现的抽象方法,判断该文件过滤器是否接受该文件
    public boolean accept(File f) {
        // 如果该文件是路径,接受该文件
        if (f.isDirectory())
            return true;
        // 将文件名转为小写(全部转为小写后比较,用于忽略文件名大小写)
        String name = f.getName().toLowerCase();
        // 遍历所有可接受的扩展名,如果扩展名相同,该文件就可接受。
        for (String extension : extensions) {
            if (name.endsWith(extension)) {
                return true;
            }
        }
        return false;
    }
}

// 创建一个ImageHolder类,用于封装图片名、图片ID
class ImageHolder {
    // 封装图片的ID
    private int id;
    // 封装图片的图片名字
    private String name;

    public ImageHolder() {
    }

    public ImageHolder(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // id的setter和getter方法
    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return this.id;
    }

    // name的setter和getter方法
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    // 重写toString方法,返回图片名
    public String toString() {
        return name;
    }
}
View Code
public class QueryExecutor {
    JFrame jf = new JFrame("查询执行器");
    private JScrollPane scrollPane;
    private JButton execBn = new JButton("查询");
    // 用于输入查询语句的文本框
    private JTextField sqlField = new JTextField(45);
    private static Connection conn;
    private static Statement stmt;
    // 采用静态初始化块来初始化Connection、Statement对象
    static {
        try {
            Properties props = new Properties();
            props.load(new FileInputStream("mysql.ini"));
            String drivers = props.getProperty("driver");
            String url = props.getProperty("url");
            String username = props.getProperty("user");
            String password = props.getProperty("pass");
            // 加载数据库驱动
            Class.forName(drivers);
            // 取得数据库连接
            conn = DriverManager.getConnection(url, username, password);
            stmt = conn.createStatement();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // --------初始化界面的方法---------
    public void init() {
        JPanel top = new JPanel();
        top.add(new JLabel("输入查询语句:"));
        top.add(sqlField);
        top.add(execBn);
        // 为执行按钮、单行文本框添加事件监听器
        execBn.addActionListener(new ExceListener());
        sqlField.addActionListener(new ExceListener());
        jf.add(top, BorderLayout.NORTH);
        jf.setSize(680, 480);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);
    }

    // 定义监听器
    class ExceListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
            // 删除原来的JTable(JTable使用scrollPane来包装)
            if (scrollPane != null) {
                jf.remove(scrollPane);
            }
            try (
            // 根据用户输入的SQL执行查询
            ResultSet rs = stmt.executeQuery(sqlField.getText())) {
                // 取出ResultSet的MetaData
                ResultSetMetaData rsmd = rs.getMetaData();
                Vector<String> columnNames = new Vector<>();
                Vector<Vector<String>> data = new Vector<>();
                // 把ResultSet的所有列名添加到Vector里
                for (int i = 0; i < rsmd.getColumnCount(); i++) {
                    columnNames.add(rsmd.getColumnName(i + 1));
                }
                // 把ResultSet的所有记录添加到Vector里
                while (rs.next()) {
                    Vector<String> v = new Vector<>();
                    for (int i = 0; i < rsmd.getColumnCount(); i++) {
                        v.add(rs.getString(i + 1));
                    }
                    data.add(v);
                }
                // 创建新的JTable
                JTable table = new JTable(data, columnNames);
                scrollPane = new JScrollPane(table);
                // 添加新的Table
                jf.add(scrollPane);
                // 更新主窗口
                jf.validate();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new QueryExecutor().init();
    }
}
View Code
public class ResultSetTest {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void query(String sql) throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 使用Connection来创建一个PreparedStatement对象
                // 传入控制结果集可滚动,可更新的参数。
                PreparedStatement pstmt = conn.prepareStatement(sql,
                        ResultSet.TYPE_SCROLL_INSENSITIVE,
                        ResultSet.CONCUR_UPDATABLE);
                ResultSet rs = pstmt.executeQuery()) {
            rs.last();
            int rowCount = rs.getRow();
            for (int i = rowCount; i > 0; i--) {
                rs.absolute(i);
                System.out.println(rs.getString(1) + "	" + rs.getString(2)
                        + "	" + rs.getString(3));
                // 修改记录指针所有记录、第2列的值
                rs.updateString(2, "学生名" + i);
                // 提交修改
                rs.updateRow();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ResultSetTest rt = new ResultSetTest();
        rt.initParam("mysql.ini");
        rt.query("select * from student_table");
    }
}
View Code

public class CachedRowSetPage {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public CachedRowSet query(String sql, int pageSize, int page)
            throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(sql)) {
            // 使用RowSetProvider创建RowSetFactory
            RowSetFactory factory = RowSetProvider.newFactory();
            // 创建默认的CachedRowSet实例
            CachedRowSet cachedRs = factory.createCachedRowSet();
            // 设置每页显示pageSize条记录
            cachedRs.setPageSize(pageSize);
            // 使用ResultSet装填RowSet,设置从第几条记录开始
            cachedRs.populate(rs, (page - 1) * pageSize + 1);
            return cachedRs;
        }
    }

    public static void main(String[] args) throws Exception {
        CachedRowSetPage cp = new CachedRowSetPage();
        cp.initParam("mysql.ini");
        CachedRowSet rs = cp.query("select * from student_table", 3, 2); //// 向后滚动结果集
        while (rs.next()) {
            System.out.println(rs.getString(1) + "	" + rs.getString(2) + "	"
                    + rs.getString(3));
        }
    }
}
View Code
public class CachedRowSetTest {
    private static String driver;
    private static String url;
    private static String user;
    private static String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public CachedRowSet query(String sql) throws Exception {
        // 加载驱动
        Class.forName(driver);
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        // 使用RowSetProvider创建RowSetFactory
        RowSetFactory factory = RowSetProvider.newFactory();
        // 创建默认的CachedRowSet实例
        CachedRowSet cachedRs = factory.createCachedRowSet();
        // 使用ResultSet装填RowSet
        cachedRs.populate(rs); //// 关闭资源
        rs.close();
        stmt.close();
        conn.close();
        return cachedRs;
    }

    public static void main(String[] args) throws Exception {
        CachedRowSetTest ct = new CachedRowSetTest();
        ct.initParam("mysql.ini");
        CachedRowSet rs = ct.query("select * from student_table");
        rs.afterLast();
        // 向前滚动结果集
        while (rs.previous()) {
            System.out.println(rs.getString(1) + "	" + rs.getString(2) + "	"
                    + rs.getString(3));
            if (rs.getInt("student_id") == 3) {
                // 修改指定记录行
                rs.updateString("student_name", "孙悟空");
                rs.updateRow();
            }
        }
        // 重新获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
        conn.setAutoCommit(false);
        // 把对RowSet所做的修改同步到底层数据库
        rs.acceptChanges(conn);
    }
}
View Code
public class JdbcRowSetTest {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void update(String sql) throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass);
                // 创建JdbcRowSetImpl对象
                JdbcRowSet jdbcRs = new JdbcRowSetImpl(conn)) //
        {
            // 设置SQL查询语句
            jdbcRs.setCommand(sql);
            // 执行查询
            jdbcRs.execute();
            jdbcRs.afterLast();
            // 向前滚动结果集
            while (jdbcRs.previous()) {
                System.out.println(jdbcRs.getString(1) + "	"
                        + jdbcRs.getString(2) + "	" + jdbcRs.getString(3));
                if (jdbcRs.getInt("student_id") == 3) {
                    // 修改指定记录行
                    jdbcRs.updateString("student_name", "孙悟空");
                    jdbcRs.updateRow();
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        JdbcRowSetTest jt = new JdbcRowSetTest();
        jt.initParam("mysql.ini");
        jt.update("select * from student_table");
    }
}
View Code
public class RowSetFactoryTest {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void update(String sql) throws Exception {
        // 加载驱动
        Class.forName(driver);
        // 使用RowSetProvider创建RowSetFactory
        RowSetFactory factory = RowSetProvider.newFactory();
        try (
        // 使用RowSetFactory创建默认的JdbcRowSet实例
        JdbcRowSet jdbcRs = factory.createJdbcRowSet()) {
            // 设置必要的连接信息
            jdbcRs.setUrl(url);
            jdbcRs.setUsername(user);
            jdbcRs.setPassword(pass);
            // 设置SQL查询语句
            jdbcRs.setCommand(sql);
            // 执行查询
            jdbcRs.execute();
            jdbcRs.afterLast();
            // 向前滚动结果集
            while (jdbcRs.previous()) {
                System.out.println(jdbcRs.getString(1) + "	"
                        + jdbcRs.getString(2) + "	" + jdbcRs.getString(3));
                if (jdbcRs.getInt("student_id") == 3) {
                    // 修改指定记录行
                    jdbcRs.updateString("student_name", "孙悟空");
                    jdbcRs.updateRow();
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        RowSetFactoryTest jt = new RowSetFactoryTest();
        jt.initParam("mysql.ini");
        jt.update("select * from student_table");
    }
}
View Code

public class TransactionTest {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void insertInTransaction(String[] sqls) throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (Connection conn = DriverManager.getConnection(url, user, pass)) {
            // 关闭自动提交,开启事务
            conn.setAutoCommit(false);
            try (
            // 使用Connection来创建一个Statment对象
            Statement stmt = conn.createStatement()) {
                // 循环多次执行SQL语句
                for (String sql : sqls) {
                    stmt.executeUpdate(sql);
                }
            }
            // 提交事务
            conn.commit();
        }
    }

    public static void main(String[] args) throws Exception {
        TransactionTest tt = new TransactionTest();
        tt.initParam("mysql.ini");
        String[] sqls = new String[] {
                "insert into student_table values(null , 'aaa' ,1)",
                "insert into student_table values(null , 'bbb' ,1)",
                "insert into student_table values(null , 'ccc' ,1)",
                // 下面这条SQL语句将会违反外键约束,
                // 因为teacher_table中没有ID为5的记录。
                "insert into student_table values(null , 'ccc' ,5)" //
        };
        tt.insertInTransaction(sqls);
    }
}
View Code
public class DatabaseMetaDataTest {
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile) throws Exception {
        // 使用Properties类来加载属性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }

    public void info() throws Exception {
        // 加载驱动
        Class.forName(driver);
        try (
        // 获取数据库连接
        Connection conn = DriverManager.getConnection(url, user, pass)) {
            // 获取的DatabaseMetaData对象
            DatabaseMetaData dbmd = conn.getMetaData();
            // 获取MySQL支持的所有表类型
            ResultSet rs = dbmd.getTableTypes();
            System.out.println("--MySQL支持的表类型信息--");
            printResultSet(rs);
            // 获取当前数据库的全部数据表
            rs = dbmd.getTables(null, null, "%", new String[] { "TABLE" });
            System.out.println("--当前数据库里的数据表信息--");
            printResultSet(rs);
            // 获取student_table表的主键
            rs = dbmd.getPrimaryKeys(null, null, "student_table");
            System.out.println("--student_table表的主键信息--");
            printResultSet(rs);
            // 获取当前数据库的全部存储过程
            rs = dbmd.getProcedures(null, null, "%");
            System.out.println("--当前数据库里的存储过程信息--");
            printResultSet(rs);
            // 获取teacher_table表和student_table之间的外键约束
            rs = dbmd.getCrossReference(null, null, "teacher_table", null,
                    null, "student_table");
            System.out.println("--teacher_table表和student_table之间" + "的外键约束--");
            printResultSet(rs);
            // 获取student_table表的全部数据列
            rs = dbmd.getColumns(null, null, "student_table", "%");
            System.out.println("--student_table表的全部数据列--");
            printResultSet(rs);
        }
    }

    public void printResultSet(ResultSet rs) throws SQLException {
        ResultSetMetaData rsmd = rs.getMetaData();
        // 打印ResultSet的所有列标题
        for (int i = 0; i < rsmd.getColumnCount(); i++) {
            System.out.print(rsmd.getColumnName(i + 1) + "	");
        }
        System.out.print("
");
        // 打印ResultSet里的全部数据
        while (rs.next()) {
            for (int i = 0; i < rsmd.getColumnCount(); i++) {
                System.out.print(rs.getString(i + 1) + "	");
            }
            System.out.print("
");
        }
        rs.close();
    }

    public static void main(String[] args) throws Exception {
        DatabaseMetaDataTest dt = new DatabaseMetaDataTest();
        dt.initParam("mysql.ini");
        dt.info();
    }
}
View Code

原文地址:https://www.cnblogs.com/pipi-changing/p/5427086.html