【12-JDBC编程】

时间:2023-03-10 02:17:18
【12-JDBC编程】

【12-JDBC编程】

JDBC编程


JDBC概述

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

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

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

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

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

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

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


JDBC驱动示意

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

图。

【12-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,即数据操作语言):主要由  insert、update和delete三个关键字完成。

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

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

•事务控制语句:主要由commit、rollback和savepoint三个关键字完成。


 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语句中使用算术运算符(+  -  *  /),从而形成算术表达式,使用算数表达式的规则如下:

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

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

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


 特殊比较运算符

【12-JDBC编程】


数据库函数

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

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

【12-JDBC编程】


组函数

•组函数也就是前面提到多行函数,组函数将一组记录作为整体计算,每一组记录返回一个结果,而不是每一条记录返回一个结果。常用的组函数有如下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) + "\t" + rs.getString(2) + "\t"
+ rs.getString(3) + "\t" + rs.getString(4));
}
}
}
}

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();
}
}
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("-----建表成功-----");
}
}
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 + "条记录受影响--");
}
}
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) + "\t");
}
System.out.print("\n");
}
}
} 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");
}
}
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();
}
}
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();
}
}

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;
}
}
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();
}
}
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) + "\t" + rs.getString(2)
+ "\t" + 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");
}
}

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) + "\t" + rs.getString(2) + "\t"
+ rs.getString(3));
}
}
}
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) + "\t" + rs.getString(2) + "\t"
+ 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);
}
}
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) + "\t"
+ jdbcRs.getString(2) + "\t" + 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");
}
}
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) + "\t"
+ jdbcRs.getString(2) + "\t" + 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");
}
}

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);
}
}
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) + "\t");
}
System.out.print("\n");
// 打印ResultSet里的全部数据
while (rs.next()) {
for (int i = 0; i < rsmd.getColumnCount(); i++) {
System.out.print(rs.getString(i + 1) + "\t");
}
System.out.print("\n");
}
rs.close();
} public static void main(String[] args) throws Exception {
DatabaseMetaDataTest dt = new DatabaseMetaDataTest();
dt.initParam("mysql.ini");
dt.info();
}
}