zoukankan      html  css  js  c++  java
  • 【12-JDBC编程】

    JDBC编程


    JDBC概述

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

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

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

     

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

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

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

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


     

     JDBC驱动示意

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

    图。

     


    JDBC驱动程序类型 

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

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

    动由Sun公司提供实现。

     

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

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

     

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

    库。

     

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

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


     

     安装MySQL

    •(1)下载MySQL安装文件

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

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

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

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


     

     MySQL的常见命令

    •show databases;

    •drop database 数据库名;

    •use 数据库名

    •show tables;

    •desc 表名


    MySQL的两种存储机制

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

     

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

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

    可以使用skip-innodb 选项。


     

     SQL语句 

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

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

     

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

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

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

    –改变数据库的结构。

    –更改系统的安全设置。

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


     

     SQL语句分类

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

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

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

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

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


     

     DDL语句 

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

    –创建(create)

    –删除(drop)

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


     

     数据库对象

    对象名称

    对应关键字

    描述

    table

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

    数据字典

     

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

    约束

    constraint

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

    视图

    view

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

    索引

    index

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

    函数

    function

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

    存储过程

    procedure

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

    触发器

    trigger

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


    创建表的语法

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

    修改表(增加列)的语法

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

     修改表(修改列)的语法

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

    修改表(删除列)的语法

    •alter table 表名

    •drop column_name


     

     删除表的语法

    •drop table 表名;


    约束

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

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

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

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

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

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


     

     索引

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

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

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

     

    •创建索引有两种方式:

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

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

     

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

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

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


     

     视图

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

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

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

    –提供了数据的独立性。

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


     

     创建视图的语法

    •create or replace view 视图名

    •as

    •subquery


     

     DML语句

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

    –插入新数据。

    –修改已有数据。

    –删除不需要的数据。


     

     insert into

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

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

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

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


     

     update语句

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

    –update table_name

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

    –[WHERE condition];


     

     delete from语句

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

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

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

    –delete from table_name

    –[WHERE condition];


     

     SELECT语句

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

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

    –select column1, column2 ...

    –from 数据源

    –[where condition]


     

     SELECT语句的规则

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

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

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

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


     

     特殊比较运算符

     


     数据库函数

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

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


    组函数

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

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

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

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

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

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


     

     多表连接查询 

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

    –等值连接。

    –非等值连接。

    –外连接。

    –广义笛卡尔积。


     

     SQL99的多表连接查询

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

    –交叉连接。

    –自然连接。

    –使用using子句的连接。

    –使用on子句的连接。

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


     

     子查询

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

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

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


     

     使用子查询的注意点

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

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

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

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

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


     

     JDBC常用接口和类 

    •DriverManager

    •Connection

    •Statement

    •PreparedStatement

    •ResultSet


    JDBC编程步骤 

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

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

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

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

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


    JDBC执行SQL语句的方式

    •使用executeUpdate执行DDL和DML语句

    •使用execute方法执行SQL语句

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


    PreparedStatement

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

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

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

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

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


     

     CallableStatment

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

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

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

     

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

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

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

    registerOutParameter方法来注册该参数。 


     

     可滚动、可更新的结果集 

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

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

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

     

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

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

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

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

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

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

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


     

     处理Blob类型数据 

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

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

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

     

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

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

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

    数据。


     

     使用ResultSetMetaData

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

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

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

     

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

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

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


     

     事务

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

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

    原子性(Atomicity)

    一致性(Consistency)

    隔离性(Isolation)

    持续性(Durability)


     

     事务的组成

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

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

    –一个 DDL 语句。

    –一个 DCL 语句。

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


     

     事务的结束

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

    –显式提交:使用commit

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

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

    –显式回滚:使用rollback

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


     

     JDBC的事务支持 

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

    conn.setAutoCommit(false);

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

    conn.commit();

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

    conn.rollback();


     

     事务的中间点

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

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

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

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

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

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


     

     批量更新

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

    集、并同时提交。

     

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

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

     

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

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


     

     DatabaseMetaData

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

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

     

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

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

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

     

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

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

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


     

     使用数据库系统表

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

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

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

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

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

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

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

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

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

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


     

     数据库连接池

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

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

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

    程序运行效率。

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

    –数据库的初始连接数。

    –连接池的最大连接数。

    –连接池的最小连接数。

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


     

     两种常见的开源数据源

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

    common-pool。

     

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

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

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


     

     现在贴出代码:

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

    public class CallableStatementTest {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void callProcedure() throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 使用Connection来创建一个CallableStatment对象
                    CallableStatement cstmt = conn
                            .prepareCall("{call add_pro(?,?,?)}")) {
                cstmt.setInt(1, 4);
                cstmt.setInt(2, 5);
                // 注册CallableStatement的第三个参数是int类型
                cstmt.registerOutParameter(3, Types.INTEGER);
                // 执行存储过程
                cstmt.execute();
                // 获取,并输出存储过程传出参数的值。
                System.out.println("执行结果是: " + cstmt.getInt(3));
            }
        }
    
        public static void main(String[] args) throws Exception {
            CallableStatementTest ct = new CallableStatementTest();
            ct.initParam("mysql.ini");
            ct.callProcedure();
        }
    }
    View Code
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/select_test
    user=root
    pass=32147
    mysql.ini
    public class ExecuteDDL {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void createTable(String sql) throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 使用Connection来创建一个Statment对象
                    Statement stmt = conn.createStatement()) {
                // 执行DDL,创建数据表
                stmt.executeUpdate(sql);
            }
        }
    
        public static void main(String[] args) throws Exception {
            ExecuteDDL ed = new ExecuteDDL();
            ed.initParam("mysql.ini");
            ed.createTable("create table jdbc_test "
                    + "( jdbc_id int auto_increment primary key, "
                    + "jdbc_name varchar(255), " + "jdbc_desc text);");
            System.out.println("-----建表成功-----");
        }
    }
    View Code
    public class ExecuteDML {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public int insertData(String sql) throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 使用Connection来创建一个Statment对象
                    Statement stmt = conn.createStatement()) {
                // 执行DML,返回受影响的记录条数
                return stmt.executeUpdate(sql);
            }
        }
    
        public static void main(String[] args) throws Exception {
            ExecuteDML ed = new ExecuteDML();
            ed.initParam("mysql.ini");
            int result = ed.insertData("insert into jdbc_test(jdbc_name,jdbc_desc)"
                    + "select s.student_name , t.teacher_name "
                    + "from student_table s , teacher_table t "
                    + "where s.java_teacher = t.teacher_id;");
            System.out.println("--系统中共有" + result + "条记录受影响--");
        }
    }
    View Code
    public class ExecuteSQL {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void executeSql(String sql) throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 使用Connection来创建一个Statement对象
                    Statement stmt = conn.createStatement()) {
                // 执行SQL,返回boolean值表示是否包含ResultSet
                boolean hasResultSet = stmt.execute(sql);
                // 如果执行后有ResultSet结果集
                if (hasResultSet) {
                    try (
                    // 获取结果集
                    ResultSet rs = stmt.getResultSet()) {
                        // ResultSetMetaData是用于分析结果集的元数据接口
                        ResultSetMetaData rsmd = rs.getMetaData();
                        int columnCount = rsmd.getColumnCount();
                        // 迭代输出ResultSet对象
                        while (rs.next()) {
                            // 依次输出每列的值
                            for (int i = 0; i < columnCount; i++) {
                                System.out.print(rs.getString(i + 1) + "	");
                            }
                            System.out.print("
    ");
                        }
                    }
                } else {
                    System.out
                            .println("该SQL语句影响的记录有" + stmt.getUpdateCount() + "条");
                }
            }
        }
    
        public static void main(String[] args) throws Exception {
            ExecuteSQL es = new ExecuteSQL();
            es.initParam("mysql.ini");
            System.out.println("------执行删除表的DDL语句-----");
            es.executeSql("drop table if exists my_test");
            System.out.println("------执行建表的DDL语句-----");
            es.executeSql("create table my_test"
                    + "(test_id int auto_increment primary key, "
                    + "test_name varchar(255))");
            System.out.println("------执行插入数据的DML语句-----");
            es.executeSql("insert into my_test(test_name) "
                    + "select student_name from student_table");
            System.out.println("------执行查询数据的查询语句-----");
            es.executeSql("select * from my_test");
        }
    }
    View Code
    public class LoginFrame {
        private final String PROP_FILE = "mysql.ini";
        private String driver;
        // url是数据库的服务地址
        private String url;
        private String user;
        private String pass;
        // 登录界面的GUI组件
        private JFrame jf = new JFrame("登录");
        private JTextField userField = new JTextField(20);
        private JTextField passField = new JTextField(20);
        private JButton loginButton = new JButton("登录");
    
        public void init()throws Exception
        {
            Properties connProp = new Properties();
            connProp.load(new FileInputStream(PROP_FILE));
            driver = connProp.getProperty("driver");
            url = connProp.getProperty("url");
            user = connProp.getProperty("user");
            pass = connProp.getProperty("pass");
            // 加载驱动
            Class.forName(driver);
            // 为登录按钮添加事件监听器
            loginButton.addActionListener(e -> {
                // 登录成功则显示“登录成功”
                if (validate(userField.getText(), passField.getText()))
                {
                    JOptionPane.showMessageDialog(jf, "登录成功");
                }
                // 否则显示“登录失败”
                else
                {
                    JOptionPane.showMessageDialog(jf, "登录失败");
                }
            });
            jf.add(userField , BorderLayout.NORTH);
            jf.add(passField);
            jf.add(loginButton , BorderLayout.SOUTH);
            jf.pack();
            jf.setVisible(true);
        }
    
        // private boolean validate(String userName, String userPass)
        // {
        // // 执行查询的SQL语句
        // String sql = "select * from jdbc_test "
        // + "where jdbc_name='" + userName
        // + "' and jdbc_desc='" + userPass + "'";
        // System.out.println(sql);
        // try(
        // Connection conn = DriverManager.getConnection(url , user ,pass);
        // Statement stmt = conn.createStatement();
        // ResultSet rs = stmt.executeQuery(sql))
        // {
        // // 如果查询的ResultSet里有超过一条的记录,则登录成功
        // if (rs.next())
        // {
        // return true;
        // }
        // }
        // catch(Exception e)
        // {
        // e.printStackTrace();
        // }
        // return false;
        // }
    
        private boolean validate(String userName, String userPass) {
            try (Connection conn = DriverManager.getConnection(url, user, pass);
                    PreparedStatement pstmt = conn
                            .prepareStatement("select * from jdbc_test where jdbc_name=? and jdbc_desc=?")) {
                pstmt.setString(1, userName);
                pstmt.setString(2, userPass);
                try (ResultSet rs = pstmt.executeQuery()) {
                    // 如果查询的ResultSet里有超过一条的记录,则登录成功
                    if (rs.next()) {
                        return true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
        public static void main(String[] args) throws Exception {
            new LoginFrame().init();
        }
    }
    View Code
    public class PreparedStatementTest {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
            // 加载驱动
            Class.forName(driver);
        }
    
        public void insertUseStatement() throws Exception {
            long start = System.currentTimeMillis();
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 使用Connection来创建一个Statment对象
                    Statement stmt = conn.createStatement()) {
                // 需要使用100条SQL语句来插入100条记录
                for (int i = 0; i < 100; i++) {
                    stmt.executeUpdate("insert into student_table values("
                            + " null ,'姓名" + i + "' , 1)");
                }
                System.out.println("使用Statement费时:"
                        + (System.currentTimeMillis() - start));
            }
        }
    
        public void insertUsePrepare() throws Exception {
            long start = System.currentTimeMillis();
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 使用Connection来创建一个PreparedStatement对象
                    PreparedStatement pstmt = conn
                            .prepareStatement("insert into student_table values(null,?,1)"))
    
            {
                // 100次为PreparedStatement的参数设值,就可以插入100条记录
                for (int i = 0; i < 100; i++) {
                    pstmt.setString(1, "姓名" + i);
                    pstmt.executeUpdate();
                }
                System.out.println("使用PreparedStatement费时:"
                        + (System.currentTimeMillis() - start));
            }
        }
    
        public static void main(String[] args) throws Exception {
            PreparedStatementTest pt = new PreparedStatementTest();
            pt.initParam("mysql.ini");
            pt.insertUseStatement();
            pt.insertUsePrepare();
        }
    }
    View Code

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/select_test
    user=root
    pass=32147
    mysql.ini
    public class BlobTest {
        JFrame jf = new JFrame("图片管理程序");
        private static Connection conn;
        private static PreparedStatement insert;
        private static PreparedStatement query;
        private static PreparedStatement queryAll;
        // 定义一个DefaultListModel对象
        private DefaultListModel<ImageHolder> imageModel = new DefaultListModel<>();
        private JList<ImageHolder> imageList = new JList<>(imageModel);
        private JTextField filePath = new JTextField(26);
        private JButton browserBn = new JButton("...");
        private JButton uploadBn = new JButton("上传");
        private JLabel imageLabel = new JLabel();
        // 以当前路径创建文件选择器
        JFileChooser chooser = new JFileChooser(".");
        // 创建文件过滤器
        ExtensionFileFilter filter = new ExtensionFileFilter();
        static {
            try {
                Properties props = new Properties();
                props.load(new FileInputStream("mysql.ini"));
                String driver = props.getProperty("driver");
                String url = props.getProperty("url");
                String user = props.getProperty("user");
                String pass = props.getProperty("pass");
                Class.forName(driver);
                // 获取数据库连接
                conn = DriverManager.getConnection(url, user, pass);
                // 创建执行插入的PreparedStatement对象,
                // 该对象执行插入后可以返回自动生成的主键
                insert = conn.prepareStatement("insert into img_table"
                        + " values(null,?,?)", Statement.RETURN_GENERATED_KEYS);
                // 创建两个PreparedStatement对象,用于查询指定图片,查询所有图片
                query = conn.prepareStatement("select img_data from img_table"
                        + " where img_id=?");
                queryAll = conn.prepareStatement("select img_id, "
                        + " img_name from img_table");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void init()throws SQLException
        {
            // -------初始化文件选择器--------
            filter.addExtension("jpg");
            filter.addExtension("jpeg");
            filter.addExtension("gif");
            filter.addExtension("png");
            filter.setDescription("图片文件(*.jpg,*.jpeg,*.gif,*.png)");
            chooser.addChoosableFileFilter(filter);
            // 禁止“文件类型”下拉列表中显示“所有文件”选项。
            chooser.setAcceptAllFileFilterUsed(false);
            // ---------初始化程序界面---------
            fillListModel();
            filePath.setEditable(false);
            // 只能单选
            imageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            JPanel jp = new JPanel();
            jp.add(filePath);
            jp.add(browserBn);
            browserBn.addActionListener(event -> {
                // 显示文件对话框
                int result = chooser.showDialog(jf , "浏览图片文件上传");
                // 如果用户选择了APPROVE(赞同)按钮,即打开,保存等效按钮
                if(result == JFileChooser.APPROVE_OPTION)
                {
                    filePath.setText(chooser.getSelectedFile().getPath());
                }
            });
            jp.add(uploadBn);
            uploadBn.addActionListener(avt -> {
                // 如果上传文件的文本框有内容
                if (filePath.getText().trim().length() > 0)
                {
                    // 将指定文件保存到数据库
                    upload(filePath.getText());
                    // 清空文本框内容
                    filePath.setText("");
                }
            });
            JPanel left = new JPanel();
            left.setLayout(new BorderLayout());
            left.add(new JScrollPane(imageLabel) , BorderLayout.CENTER);
            left.add(jp , BorderLayout.SOUTH);
            jf.add(left);
            imageList.setFixedCellWidth(160);
            jf.add(new JScrollPane(imageList) , BorderLayout.EAST);
            imageList.addMouseListener(new MouseAdapter()
            {
                public void mouseClicked(MouseEvent e)
                {
                    // 如果鼠标双击
                    if (e.getClickCount() >= 2)
                    {
                        // 取出选中的List项
                        ImageHolder cur = (ImageHolder)imageList.
                        getSelectedValue();
                        try
                        {
                            // 显示选中项对应的Image
                            showImage(cur.getId());
                        }
                        catch (SQLException sqle)
                        {
                            sqle.printStackTrace();
                        }
                    }
                }
            });
            jf.setSize(620, 400);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jf.setVisible(true);
        }
    
        // ----------查找img_table填充ListModel----------
        public void fillListModel() throws SQLException {
    
            try (
            // 执行查询
            ResultSet rs = queryAll.executeQuery()) {
                // 先清除所有元素
                imageModel.clear();
                // 把查询的全部记录添加到ListModel中
                while (rs.next()) {
                    imageModel.addElement(new ImageHolder(rs.getInt(1), rs
                            .getString(2)));
                }
            }
        }
    
        // ---------将指定图片放入数据库---------
        public void upload(String fileName) {
            // 截取文件名
            String imageName = fileName.substring(fileName.lastIndexOf('\') + 1,
                    fileName.lastIndexOf('.'));
            File f = new File(fileName);
            try (InputStream is = new FileInputStream(f)) {
                // 设置图片名参数
                insert.setString(1, imageName);
                // 设置二进制流参数
                insert.setBinaryStream(2, is, (int) f.length());
                int affect = insert.executeUpdate();
                if (affect == 1) {
                    // 重新更新ListModel,将会让JList显示最新的图片列表
                    fillListModel();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        // ---------根据图片ID来显示图片----------
        public void showImage(int id) throws SQLException {
            // 设置参数
            query.setInt(1, id);
            try (
            // 执行查询
            ResultSet rs = query.executeQuery()) {
                if (rs.next()) {
                    // 取出Blob列
                    Blob imgBlob = rs.getBlob(1);
                    // 取出Blob列里的数据
                    ImageIcon icon = new ImageIcon(imgBlob.getBytes(1L,
                            (int) imgBlob.length()));
                    imageLabel.setIcon(icon);
                }
            }
        }
    
        public static void main(String[] args) throws SQLException {
            new BlobTest().init();
        }
    }
    
    // 创建FileFilter的子类,用以实现文件过滤功能
    class ExtensionFileFilter extends FileFilter {
        private String description = "";
        private ArrayList<String> extensions = new ArrayList<>();
    
        // 自定义方法,用于添加文件扩展名
        public void addExtension(String extension) {
            if (!extension.startsWith(".")) {
                extension = "." + extension;
                extensions.add(extension.toLowerCase());
            }
        }
    
        // 用于设置该文件过滤器的描述文本
        public void setDescription(String aDescription) {
            description = aDescription;
        }
    
        // 继承FileFilter类必须实现的抽象方法,返回该文件过滤器的描述文本
        public String getDescription() {
            return description;
        }
    
        // 继承FileFilter类必须实现的抽象方法,判断该文件过滤器是否接受该文件
        public boolean accept(File f) {
            // 如果该文件是路径,接受该文件
            if (f.isDirectory())
                return true;
            // 将文件名转为小写(全部转为小写后比较,用于忽略文件名大小写)
            String name = f.getName().toLowerCase();
            // 遍历所有可接受的扩展名,如果扩展名相同,该文件就可接受。
            for (String extension : extensions) {
                if (name.endsWith(extension)) {
                    return true;
                }
            }
            return false;
        }
    }
    
    // 创建一个ImageHolder类,用于封装图片名、图片ID
    class ImageHolder {
        // 封装图片的ID
        private int id;
        // 封装图片的图片名字
        private String name;
    
        public ImageHolder() {
        }
    
        public ImageHolder(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        // id的setter和getter方法
        public void setId(int id) {
            this.id = id;
        }
    
        public int getId() {
            return this.id;
        }
    
        // name的setter和getter方法
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return this.name;
        }
    
        // 重写toString方法,返回图片名
        public String toString() {
            return name;
        }
    }
    View Code
    public class QueryExecutor {
        JFrame jf = new JFrame("查询执行器");
        private JScrollPane scrollPane;
        private JButton execBn = new JButton("查询");
        // 用于输入查询语句的文本框
        private JTextField sqlField = new JTextField(45);
        private static Connection conn;
        private static Statement stmt;
        // 采用静态初始化块来初始化Connection、Statement对象
        static {
            try {
                Properties props = new Properties();
                props.load(new FileInputStream("mysql.ini"));
                String drivers = props.getProperty("driver");
                String url = props.getProperty("url");
                String username = props.getProperty("user");
                String password = props.getProperty("pass");
                // 加载数据库驱动
                Class.forName(drivers);
                // 取得数据库连接
                conn = DriverManager.getConnection(url, username, password);
                stmt = conn.createStatement();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        // --------初始化界面的方法---------
        public void init() {
            JPanel top = new JPanel();
            top.add(new JLabel("输入查询语句:"));
            top.add(sqlField);
            top.add(execBn);
            // 为执行按钮、单行文本框添加事件监听器
            execBn.addActionListener(new ExceListener());
            sqlField.addActionListener(new ExceListener());
            jf.add(top, BorderLayout.NORTH);
            jf.setSize(680, 480);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jf.setVisible(true);
        }
    
        // 定义监听器
        class ExceListener implements ActionListener {
            public void actionPerformed(ActionEvent evt) {
                // 删除原来的JTable(JTable使用scrollPane来包装)
                if (scrollPane != null) {
                    jf.remove(scrollPane);
                }
                try (
                // 根据用户输入的SQL执行查询
                ResultSet rs = stmt.executeQuery(sqlField.getText())) {
                    // 取出ResultSet的MetaData
                    ResultSetMetaData rsmd = rs.getMetaData();
                    Vector<String> columnNames = new Vector<>();
                    Vector<Vector<String>> data = new Vector<>();
                    // 把ResultSet的所有列名添加到Vector里
                    for (int i = 0; i < rsmd.getColumnCount(); i++) {
                        columnNames.add(rsmd.getColumnName(i + 1));
                    }
                    // 把ResultSet的所有记录添加到Vector里
                    while (rs.next()) {
                        Vector<String> v = new Vector<>();
                        for (int i = 0; i < rsmd.getColumnCount(); i++) {
                            v.add(rs.getString(i + 1));
                        }
                        data.add(v);
                    }
                    // 创建新的JTable
                    JTable table = new JTable(data, columnNames);
                    scrollPane = new JScrollPane(table);
                    // 添加新的Table
                    jf.add(scrollPane);
                    // 更新主窗口
                    jf.validate();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            new QueryExecutor().init();
        }
    }
    View Code
    public class ResultSetTest {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void query(String sql) throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 使用Connection来创建一个PreparedStatement对象
                    // 传入控制结果集可滚动,可更新的参数。
                    PreparedStatement pstmt = conn.prepareStatement(sql,
                            ResultSet.TYPE_SCROLL_INSENSITIVE,
                            ResultSet.CONCUR_UPDATABLE);
                    ResultSet rs = pstmt.executeQuery()) {
                rs.last();
                int rowCount = rs.getRow();
                for (int i = rowCount; i > 0; i--) {
                    rs.absolute(i);
                    System.out.println(rs.getString(1) + "	" + rs.getString(2)
                            + "	" + rs.getString(3));
                    // 修改记录指针所有记录、第2列的值
                    rs.updateString(2, "学生名" + i);
                    // 提交修改
                    rs.updateRow();
                }
            }
        }
    
        public static void main(String[] args) throws Exception {
            ResultSetTest rt = new ResultSetTest();
            rt.initParam("mysql.ini");
            rt.query("select * from student_table");
        }
    }
    View Code

    public class CachedRowSetPage {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public CachedRowSet query(String sql, int pageSize, int page)
                throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    Statement stmt = conn.createStatement();
                    ResultSet rs = stmt.executeQuery(sql)) {
                // 使用RowSetProvider创建RowSetFactory
                RowSetFactory factory = RowSetProvider.newFactory();
                // 创建默认的CachedRowSet实例
                CachedRowSet cachedRs = factory.createCachedRowSet();
                // 设置每页显示pageSize条记录
                cachedRs.setPageSize(pageSize);
                // 使用ResultSet装填RowSet,设置从第几条记录开始
                cachedRs.populate(rs, (page - 1) * pageSize + 1);
                return cachedRs;
            }
        }
    
        public static void main(String[] args) throws Exception {
            CachedRowSetPage cp = new CachedRowSetPage();
            cp.initParam("mysql.ini");
            CachedRowSet rs = cp.query("select * from student_table", 3, 2); //// 向后滚动结果集
            while (rs.next()) {
                System.out.println(rs.getString(1) + "	" + rs.getString(2) + "	"
                        + rs.getString(3));
            }
        }
    }
    View Code
    public class CachedRowSetTest {
        private static String driver;
        private static String url;
        private static String user;
        private static String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public CachedRowSet query(String sql) throws Exception {
            // 加载驱动
            Class.forName(driver);
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(sql);
            // 使用RowSetProvider创建RowSetFactory
            RowSetFactory factory = RowSetProvider.newFactory();
            // 创建默认的CachedRowSet实例
            CachedRowSet cachedRs = factory.createCachedRowSet();
            // 使用ResultSet装填RowSet
            cachedRs.populate(rs); //// 关闭资源
            rs.close();
            stmt.close();
            conn.close();
            return cachedRs;
        }
    
        public static void main(String[] args) throws Exception {
            CachedRowSetTest ct = new CachedRowSetTest();
            ct.initParam("mysql.ini");
            CachedRowSet rs = ct.query("select * from student_table");
            rs.afterLast();
            // 向前滚动结果集
            while (rs.previous()) {
                System.out.println(rs.getString(1) + "	" + rs.getString(2) + "	"
                        + rs.getString(3));
                if (rs.getInt("student_id") == 3) {
                    // 修改指定记录行
                    rs.updateString("student_name", "孙悟空");
                    rs.updateRow();
                }
            }
            // 重新获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
            conn.setAutoCommit(false);
            // 把对RowSet所做的修改同步到底层数据库
            rs.acceptChanges(conn);
        }
    }
    View Code
    public class JdbcRowSetTest {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void update(String sql) throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass);
                    // 创建JdbcRowSetImpl对象
                    JdbcRowSet jdbcRs = new JdbcRowSetImpl(conn)) //
            {
                // 设置SQL查询语句
                jdbcRs.setCommand(sql);
                // 执行查询
                jdbcRs.execute();
                jdbcRs.afterLast();
                // 向前滚动结果集
                while (jdbcRs.previous()) {
                    System.out.println(jdbcRs.getString(1) + "	"
                            + jdbcRs.getString(2) + "	" + jdbcRs.getString(3));
                    if (jdbcRs.getInt("student_id") == 3) {
                        // 修改指定记录行
                        jdbcRs.updateString("student_name", "孙悟空");
                        jdbcRs.updateRow();
                    }
                }
            }
        }
    
        public static void main(String[] args) throws Exception {
            JdbcRowSetTest jt = new JdbcRowSetTest();
            jt.initParam("mysql.ini");
            jt.update("select * from student_table");
        }
    }
    View Code
    public class RowSetFactoryTest {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void update(String sql) throws Exception {
            // 加载驱动
            Class.forName(driver);
            // 使用RowSetProvider创建RowSetFactory
            RowSetFactory factory = RowSetProvider.newFactory();
            try (
            // 使用RowSetFactory创建默认的JdbcRowSet实例
            JdbcRowSet jdbcRs = factory.createJdbcRowSet()) {
                // 设置必要的连接信息
                jdbcRs.setUrl(url);
                jdbcRs.setUsername(user);
                jdbcRs.setPassword(pass);
                // 设置SQL查询语句
                jdbcRs.setCommand(sql);
                // 执行查询
                jdbcRs.execute();
                jdbcRs.afterLast();
                // 向前滚动结果集
                while (jdbcRs.previous()) {
                    System.out.println(jdbcRs.getString(1) + "	"
                            + jdbcRs.getString(2) + "	" + jdbcRs.getString(3));
                    if (jdbcRs.getInt("student_id") == 3) {
                        // 修改指定记录行
                        jdbcRs.updateString("student_name", "孙悟空");
                        jdbcRs.updateRow();
                    }
                }
            }
        }
    
        public static void main(String[] args) throws Exception {
            RowSetFactoryTest jt = new RowSetFactoryTest();
            jt.initParam("mysql.ini");
            jt.update("select * from student_table");
        }
    }
    View Code

    public class TransactionTest {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void insertInTransaction(String[] sqls) throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (Connection conn = DriverManager.getConnection(url, user, pass)) {
                // 关闭自动提交,开启事务
                conn.setAutoCommit(false);
                try (
                // 使用Connection来创建一个Statment对象
                Statement stmt = conn.createStatement()) {
                    // 循环多次执行SQL语句
                    for (String sql : sqls) {
                        stmt.executeUpdate(sql);
                    }
                }
                // 提交事务
                conn.commit();
            }
        }
    
        public static void main(String[] args) throws Exception {
            TransactionTest tt = new TransactionTest();
            tt.initParam("mysql.ini");
            String[] sqls = new String[] {
                    "insert into student_table values(null , 'aaa' ,1)",
                    "insert into student_table values(null , 'bbb' ,1)",
                    "insert into student_table values(null , 'ccc' ,1)",
                    // 下面这条SQL语句将会违反外键约束,
                    // 因为teacher_table中没有ID为5的记录。
                    "insert into student_table values(null , 'ccc' ,5)" //
            };
            tt.insertInTransaction(sqls);
        }
    }
    View Code
    public class DatabaseMetaDataTest {
        private String driver;
        private String url;
        private String user;
        private String pass;
    
        public void initParam(String paramFile) throws Exception {
            // 使用Properties类来加载属性文件
            Properties props = new Properties();
            props.load(new FileInputStream(paramFile));
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            pass = props.getProperty("pass");
        }
    
        public void info() throws Exception {
            // 加载驱动
            Class.forName(driver);
            try (
            // 获取数据库连接
            Connection conn = DriverManager.getConnection(url, user, pass)) {
                // 获取的DatabaseMetaData对象
                DatabaseMetaData dbmd = conn.getMetaData();
                // 获取MySQL支持的所有表类型
                ResultSet rs = dbmd.getTableTypes();
                System.out.println("--MySQL支持的表类型信息--");
                printResultSet(rs);
                // 获取当前数据库的全部数据表
                rs = dbmd.getTables(null, null, "%", new String[] { "TABLE" });
                System.out.println("--当前数据库里的数据表信息--");
                printResultSet(rs);
                // 获取student_table表的主键
                rs = dbmd.getPrimaryKeys(null, null, "student_table");
                System.out.println("--student_table表的主键信息--");
                printResultSet(rs);
                // 获取当前数据库的全部存储过程
                rs = dbmd.getProcedures(null, null, "%");
                System.out.println("--当前数据库里的存储过程信息--");
                printResultSet(rs);
                // 获取teacher_table表和student_table之间的外键约束
                rs = dbmd.getCrossReference(null, null, "teacher_table", null,
                        null, "student_table");
                System.out.println("--teacher_table表和student_table之间" + "的外键约束--");
                printResultSet(rs);
                // 获取student_table表的全部数据列
                rs = dbmd.getColumns(null, null, "student_table", "%");
                System.out.println("--student_table表的全部数据列--");
                printResultSet(rs);
            }
        }
    
        public void printResultSet(ResultSet rs) throws SQLException {
            ResultSetMetaData rsmd = rs.getMetaData();
            // 打印ResultSet的所有列标题
            for (int i = 0; i < rsmd.getColumnCount(); i++) {
                System.out.print(rsmd.getColumnName(i + 1) + "	");
            }
            System.out.print("
    ");
            // 打印ResultSet里的全部数据
            while (rs.next()) {
                for (int i = 0; i < rsmd.getColumnCount(); i++) {
                    System.out.print(rs.getString(i + 1) + "	");
                }
                System.out.print("
    ");
            }
            rs.close();
        }
    
        public static void main(String[] args) throws Exception {
            DatabaseMetaDataTest dt = new DatabaseMetaDataTest();
            dt.initParam("mysql.ini");
            dt.info();
        }
    }
    View Code

  • 相关阅读:
    G
    C
    B
    B
    线段树模板
    网络流模板
    POJ_1631_Bridging_Signals_(动态规划,LIS)
    POJ_1065_Wooden_Sticks_(动态规划,LIS+鸽笼原理)
    BZOJ_1015_星球大战_[JSOI2008]_(并查集)
    POJ_3280_Cheapest_Palindrome_(动态规划)
  • 原文地址:https://www.cnblogs.com/pipi-changing/p/5427086.html
Copyright © 2011-2022 走看看