【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,即数据操作语言):主要由 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)数据库对象。
数据库对象
创建表的语法
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); create table user_inf ( user_id int primary key auto_increment, user_name varchar(255) ); 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 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
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(); } }
|