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); 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(); } } |
【12-JDBC编程】
时间: 2024-10-29 19:10:22
【12-JDBC编程】的相关文章
JDBC编程总结
JDBC编程总结 JDBC的基本原理JDBC是Java操作数据库的技术规范.他实际上定义了一组标准的操作数据库的接口.为了能让Java操作数据库,必须要有实现了JDBC这些接口的类,不同的数据库厂商为了让Java语言能操作自己的数据库,都提供了对JDBC接口的实现--这些实现了JDBC接口的类打成一个jar包,就是我们平时看到的数据库驱动.由于不同的数据库操作数据的机制不一样,因此JDBC的具体实现也就千差万别,但是你作为java程序员,你只和Java JDBC的接口打交到,才不用理会他们怎么实
JDBC编程 之 增删改查
JDBC编程之数据增加,更改,查询,删除 1 package com.good.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.Statement; 7 8 public class Main { 9 //1数据库连接的方法就独立出来了 10 public static Connection getConnec
JDBC编程理论知识(1)
1.SUN公司为统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC 2.JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成. 组成JDBC的2个包: (1)java.sql.*; (2)javax.sql.*; 3.JDBC在程序中的位置: 4.JDBC的六个固定步骤 1,注册数据库驱动[利用反射] 2,取得数据库连接对象Connection 3,创建SQL对象 4,执行SQL命令,并返回结果集 5,处理结果集 6,
第15篇-JAVA JDBC编程
第15篇-JAVA JDBC编程 每篇一句 :对于勇敢者,尝试是一条崭新的生活之路 初学心得: 但对于坎坷与泥泞,能以平常之心视之,就非常不容易 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-05-08| JAVA JDBC编程 ] 1.JDBC概述 通过使用JDBC API,Java程序可以非常方便地操作各种主流数据库,这是是Java语言的巨大魅力所在 由于Java语言的跨平台特性,所以使用JDBC API所编写的程序不仅可以实现跨数据库,还可以跨平台,具有非常优秀的可移植性
02Mybatis_原生态jdbc编程中的问题总结——从而引生出为什么要用Mybatis
我们先用jdbc去编写一个例子: 第一步:建表 1 /* 2 SQLyog v10.2 3 MySQL - 5.1.72-community : Database - mybatis 4 ********************************************************************* 5 */ 6 7 8 /*!40101 SET NAMES utf8 */; 9 10 /*!40101 SET SQL_MODE=''*/; 11 12 /*!40014
JavaEE之JDBC编程[详解]
1.数据库简介 数据库(DB,Data Base ) 数据库管理系统(DBMS,Data Base Management System) 关系型数据库(RDB) 关系型数据库管理系统(RDBMS) SQL语言(Structured Query Language):使用关系模型的数据库语言,用于和各类数据库的交互,提供通用的数据管理和查询功能. 常用SQL指令:(CURD) SELECT .INSERT.DELETE.UPDATE.CREATE.DROP ODBC(Open DataBase Co
第十三章.MySQL数据库与JDBC编程(下)
JDBC的典型用法: JDBC4.2常用接口和类简介: DriverManager:用于管理JDBC驱动的服务类,程序中使用该类的主要功能是获取Connection对象,该类包含如下方法: public static synchronized Connection getConnection(String url, String user, String pass) throws SQLException:该方法获得url对应数据库的连接 Connection:代表数据库连接对象,每个Conn
第13章 MySQL数据库与JDBC编程
13.1 JDBC基础 13.1.1 JDBC简介 13.1.2 JDBC驱动程序 13.2 SQL语法 13.2.1 安装数据库 13.2.2 关系数据库基本概念和MySQL基本命令 13.2.3 SQL语句基础 13.2.4 DDL语言 13.2.5 数据库约束 13.2.6 索引 13.2.7 视图 13.2.8 DML语句语法 13.2.9 单表查询 13.2.10 数据库函数 13.2.11 分组和组函数 13.2.12 多表连接查询 13.2.13 子查询 13.2.14 集合查询
JDBC编程之预编译SQL与防注入式攻击以及PreparedStatement的使用教程
在JDBC编程中,常用Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程. 1.Statement 该对象用于执行静态的 SQL 语句,并且返回执行结果. 此处的SQL语句必须是完整的,有明确的数据指示.查的是哪条记录?改的是哪条记录?都要指示清楚. 通过调用
JDBC编程的步骤
一.进行JDBC编程的步骤大致如下: 1. 加载数据库驱动,通常使用Class类的forName()静态方法来加载驱动.如下代码: Class.forName(dirvirClass) 上面代码中的driverClass就是数据库驱动类所对应的字符串 加载MySQL数据库时采用的代码为: Class.forName("com.mysql.jdbc.Driver"); 2. 通过DriverManager获取数据库连接. DriverManager.getConnec