Java数据库编程之【Derby数据库】【JDBC创建数据库例程】【三】
Java数据库编程【Derby数据库】【JDBC例程】
- 15.4 Derby数据库编程基础
- 15.4.1 Derby数据库开发环境
- 15.4.2 Derby数据库字段数据类型
- 15.4.3 Derby数据库嵌入模式与网络服务器模式比较
- 15.5 JDBC数据库操作例程
- 15.5.1创建数据库例程DbUtil
- 15.5.2 创建数据库例程CreateDB
15.4 Derby数据库编程基础
Java有一个内置的 Derby 数据库,是一个完全用Java语言编写的、功能强大的微型数据库,其基础引擎和内嵌的JDBC驱动总共大约2MB大小。Derby为用户提供了轻量的标准数据库引擎,它可以紧密地嵌入到任何基于Java的解决方案中。
Derby的特性令人惊奇,它可以支持关系数据库中的所有企业级的特性,包括崩溃恢复、事务回滚和提交、行/表级锁、视图、主键/外键约束、触发器、子查询表达式,等等。
Derby数据库可以有两种部署方式:
- 嵌入式:Derby数据库提供了嵌入式的JDBC驱动,因此可把Derby数据库嵌入到Java应用程序内。这种模式的Derby数据库适用于单个用户的Java应用程序,Derby和应用程序运行在同一个JVM中。Derby对于应用用户几乎是透明的,因为它的启动和终止都是由应用程序来控制,而不需要任何第三方系统的管理。这种模式是Derby数据库独有的,使用嵌入式驱动就可在Java应用程序中嵌入并使用Derby数据库,数据库与应用程序浑然一体。它的特点是单用户访问:嵌入模式下,数据库只能由运行它的应用程序访问,不支持多用户并发访问。
- 网络服务器模式:这是标准的数据库服务器(服务器/客户端)模式,是所有的数据库产品都支持的模式。应用程序作为客户端,通过网络连接数据库服务器后,才能对数据库中的数据进行操作。数据库服务器是独立部署的。在这种模式下,Derby数据库独立进行启动管理,其他应用程序可以通过网络连接访问数据库。这种模式下,Derby数据库以一个独立的JVM运行在服务器主机中。java应用程序也在各自的JVM中运行,应用程序以“服务器/客户端”模式通过网络连接数据库服务器来访问数据库。
Derby数据库基于Java、JDBC和SQL标准,它的安装、部署和使用非常简单,非常适合我们初学者来学习数据库程序设计。
在本书中主要介绍与Java应用程序访问Derby数据库相关的内容,也有个别例程演示访问MySQL数据库。
15.4.1 Derby数据库开发环境
从JDK1.6开始,Java就集成了Derby数据库,其在JDK中的位置(jdk后面的数字编号是版本号):“C:\Program Files(x86)\Java\jdk1.7.0_79\db”。这个db文件夹就是derby数据库部署包,它有两个子目录bin和lib。子目录bin中有一组数据库管理工具,如数据库管理工具 ij 工具、服务器模式所需的管理工具startNetworkServer和stopNetworkServer等等。 子目录lib中是数据库相关的jar包,有两个最重要的jar包,derby.jar是Derby数据库驱动类;derbytools.jar则是数据库工具包。Derby数据库编程,就需要用数据库驱动类derby.jar。
如果JDK中没有derby数据库部署包,也可以从网上下载。
如果你使用集成开发环境Eclipse,就需要配置一下项目的构建路径。
当项目中需要使用第三方库文件(jar包)时,通常需要配置项目构建路径。
下面用设置derby数据库开发环境为例,在项目中增加jar包derby.jar的路径。设置前把derby.jar文件先拷贝到某路径下,本例为“D:\workspace_new\JavaTest\src\lib”。
配置项目的构建路径(Configure Build Path)的设置步骤如下:
在包资源管理器(Package Explorer)中右键点击项目名称(或程序源码文件),将弹出菜单如下图(这是英文版本),把光标移到“Build Path”(构建路径),在弹出的级联菜单中点击“Configure Build Path”;
弹出配置页面如下,先点击页面标签“Libraries”,再点击按钮“Add External JARs…”(增加外部的JAR包);
弹出“JAR Selection”(JAR包选择)配置页面如下,找到并点击路径下的derby.jar,再单击“打开”按钮完成设置。设置后中间多了一行如上图的“derby.jar -”这行。至此该项目就可以使用derby数据库了。
15.4.2 Derby数据库字段数据类型
说明: 标准的SQL语句是不区分大小写的,也即大小写不敏感的。因此,上面的数据类型DATE与Date、DOUBLE与Double、BLOB与Blob、TIMSTAMP与TimStamp表示同样的数据类型。
但是也与系统环境有点关系,在Unix和Linux系统环境中,由于系统环境本身是大小写敏感的,通常可通过数据库配置文件中的相关参数选项来进行设定(是否大小写敏感)。
类型DECIMAL,例如:price DECIMAL(5,2)表示数值最多可有5位数字,其中整数位最多可占3位,小数位占2位。
时间戳类型TIMESTAMP是把DATE和TIME类型组合为一个类型,例如:如下可表示一个时间戳的值:‘2012-01-13 08:08:08’。
数据类型的匹配
数据库中使用的数据类型是java.sql.*中定义的SQL数据类型,有些类型可与Java基本类型对应,有些不能对应。因此,当应用程序从数据库结果集中提取数据时,需要考虑数据类型的匹配,常见的有三种匹配方式:
- 与Java基本类型对应的,可赋值给基本类型的变量。SMALLINT、INT可用基本数据类型int;BIGINT可用基本数据类型long;REAL、DOUBLE可用基本数据类型double;CHAR、VARCHAR可用基本数据类型String。
- 货币金额等准确数值表示,如DECIMAL,可赋值给java.math.BigDecimal数据类型;SQL的DATE类型,可赋值给 java.util.Date数据类型。
- 无对应数值类型的可直接用SQL的数值类型,如TIMSTAMP、BLOB和CLOB。
BLOB和CLOB是大对象类型后面有章节介绍。下面是 TIMSTAMP 的使用示例:
Timestamp tmstamp = new Timestamp(System.currentTimeMillis()); //当前时间的时间戳Timestamp datetime = Timestamp.valueOf(LocalDateTime.now()); //当前时间的时间戳Timestamp timestamp = Timestamp.valueOf("2020-01-16 16:15:56.186"); //字符串生成
Derby 数据库表中字段名的命名规则:
- 必须以字母开头,字段名允许包含字符和数字以及下划线;
- 最长128个字符;
- 字段名不区分大小写。
15.4.3 Derby数据库嵌入模式与网络服务器模式比较
Apache Derby 是一个轻量级的关系型数据库,支持两种运行模式:嵌入模式(Embedded Mode)和网络服务器模式(Network Server Mode)。这两种模式在架构、使用场景和配置上有显著区别。
- 嵌入模式(Embedded Mode)
在嵌入模式下,Derby 数据库引擎直接运行在应用程序的 JVM 中,数据库与应用程序共享同一个进程。
嵌入模式的特点:
-
单用户访问:嵌入模式下,数据库只能由运行它的应用程序访问,不支持多用户并发访问。
-
无网络通信:数据库与应用程序之间通过本地调用通信,无需网络连接。
-
零配置:嵌入模式通常不需要额外的配置,数据库文件直接存储在本地文件系统中。
-
轻量级:由于不需要独立的数据库服务器进程,嵌入模式非常轻量,适合嵌入式应用或单机应用。
嵌入模式的使用场景
-
桌面应用程序。
-
单用户应用程序。
-
嵌入式系统(如移动设备或 IoT 设备)。
-
开发和测试环境。
- 网络服务器模式(Network Server Mode)
在网络服务器模式下,Derby 作为一个独立的数据库服务器运行,可以通过网络接受多个客户端的连接请求。
网络服务器模式特点:
- 多用户访问:支持多个客户端并发访问数据库。
- 网络通信:客户端通过 TCP/IP 协议与 Derby 服务器通信。
- 独立进程:Derby 服务器作为一个独立的进程运行,与应用程序分离。
- 需要配置:需要启动 Derby 服务器,并配置网络连接参数(如端口号)。
网络服务器模式使用场景:
- 多用户应用程序。
- 分布式系统。
- 生产环境。
总结
-
嵌入模式:适合单用户、单机应用,数据库引擎与应用程序共享同一个 JVM,无需网络通信。
-
网络服务器模式:适合多用户、分布式应用,数据库作为独立进程运行,支持网络访问。
根据应用场景和需求选择合适的模式,可以充分发挥 Derby 数据库的优势。
15.5 JDBC数据库操作例程
本书主要使用Derby数据库来演示如何用JDBC操作数据库,部分例程使用MySQL来演示。JDBC程序可以设计得很通用,我们先提供一个数据库基本操作的工具演示类DbUtil,然后使用不同的数据库和不同的形式来测试演示。
只要你学会了某一种数据库的JDBC操作数据库,换另一种数据库亦是大同小异,程序代码基本相同。
15.5.1创建数据库例程DbUtil
数据库操作工具演示类DbUtil定义了一些使用JDBC创建数据库表、插入数据和查询数据的通用的静态方法。
我们先给出一个完整的演示程序,然后讲解,如何使用不同的数据库环境,在类DbUtil的main方法中编写测试演示代码进行测试。虽然数据库环境不同,但测试结果是相同的。
DbUtil.java例程的学生数据库包含一个数据库表,这是表的定义:
【例程15-3】创建数据库表及简单操作的工具类例程DbUtil
package db.dbUtil;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
public class DbUtil {/***删除学生基本信息表student的SQL语句脚本***/public static final String DropStudentTableSQL = "DROP TABLE student" ; /***创建学生基本信息表student的SQL语句脚本***/public static final String CrtStudentTableSQL = "CREATE TABLE student ( " +"studentID CHAR(6) PRIMARY KEY," +"name VARCHAR(8) NOT NULL," +"height REAL check(height>=0)," +"birthDay DATE )" ;/***插入信息到学生基本信息表student的SQL语句脚本***/public static final String InitStudentTableSQL ="INSERT INTO student(studentID, name, height,birthDay)"+ " VALUES ('200001','高玉宝',1.75,'2002-05-08'),"+" ('200002','赵云',1.72,'2001-06-08'),"+" ('200003','李云龙',1.76,'2000-07-18'),"+" ('200004','钱江',1.70,'2001-10-08'),"+" ('200005','刘胡兰',1.56,'2002-06-01')"; public static final String QuerySQL = "SELECT * from student "+"where StudentID = '200005'";public static final String QuerySQL2 = "SELECT * from student where 1=1";private static String driver; //数据库驱动private static String dbProtocol;//数据库协议private static String dbName ; //数据库名称private static Connection con = null ;//初始化设置参数方法public static void setParameter(String driver,String protocol,String db) {DbUtil.driver = driver;dbProtocol = protocol;dbName = db;}//根据参数,删除数据库表public static void DropTable(String dropTableSQL){ UpdateDB(dropTableSQL); }//根据建表参数,新建数据库表public static void CreateDbTable(String createTableSQL){ UpdateDB( createTableSQL ); }//根据sql参数,更新数据库表public static void UpdateDB(String sql){ /**数据库连接url: "create=true"表示如果数据库不存在,就新建之。**/String url = dbProtocol + dbName ;// + ";create=true";try {if (con==null) { //如果数据库连接不存在,建立数据库连接Class.forName(driver) ; /***加载数据库驱动***/con = DriverManager.getConnection(url); //建立数据库连接}Statement stmt = con.createStatement();stmt.executeUpdate(sql); //执行更新stmt.close();}catch (SQLException se) {PrintSQLException(se) ;}catch(ClassNotFoundException e){System.err.println("JDBC Driver:" + driver + " not in CLASSPATH");}}//根据参数,删除数据库表public static void DropTable(String dropTableSQL,String user,String password){ UpdateDB(dropTableSQL,user,password); }//根据建表参数,新建数据库表public static void CreateDbTable(String createTableSQL,String user,String password){ UpdateDB( createTableSQL,user,password ); }//根据sql参数、user和password,更新数据库表public static void UpdateDB(String sql,String user,String password){ /**数据库连接url: "create=true"表示如果数据库不存在,就新建之。**/String url = dbProtocol + dbName ; // + ";create=true";try {if (con==null) { //如果数据库连接不存在,建立数据库连接Class.forName(driver) ; /***加载数据库驱动***///建立数据库连接con = DriverManager.getConnection(url,user,password);}Statement stmt = con.createStatement();stmt.executeUpdate(sql); //执行更新stmt.close();}catch (SQLException se) {PrintSQLException(se) ;}catch(ClassNotFoundException e){System.err.println("JDBC Driver:" + driver + " not in CLASSPATH");}}/***查询并打印信息的方法***/public static void QueryInf(String sql) {String url = dbProtocol + dbName ;try {if (con==null) { //如果数据库连接不存在,建立数据库连接Class.forName(driver) ; /***加载数据库驱动***///建立数据库连接con = DriverManager.getConnection(url);}Statement stmt = con.createStatement();ResultSet rSet = stmt.executeQuery(sql);//执行查询while(rSet.next()) {String idStr = rSet.getString("studentID");String name = rSet.getString("name");Date date = rSet.getDate("birthDay");System.out.println(idStr+'\t'+name+'\t'+date.toString());}stmt.close();}catch (SQLException se) {PrintSQLException(se) ;}catch(ClassNotFoundException e){System.err.println("JDBC Driver:" + driver + " not in CLASSPATH");}}/***打印SQLException异常出错信息的方法***/public static void PrintSQLException(SQLException se) {while(se != null) {System.out.print("SQLException: State: " + se.getSQLState());System.out.println(" Severity: " + se.getErrorCode());System.out.println(se.getMessage()); se = se.getNextException();}} /***打印SQLWarning警告信息的方法***/public static void PrintSQLWarning(SQLWarning sw) {while(sw != null) {System.out.print("SQLWarning: State=" + sw.getSQLState()) ;System.out.println(" Severity = " + sw.getErrorCode()) ;System.out.println(sw.getMessage()); sw = sw.getNextWarning();}}
public static void main(String[] args) {
/***这是Derby嵌入式数据库的代码***/String driver = "org.apache.derby.jdbc.EmbeddedDriver" ; //Derby嵌入式数据库驱动String dbProtocol="jdbc:derby:" ;//数据库协议String dbName = "D:\\DB\\StudentDB;create=true"; //***下面演示数据库表的创建、数据插入、查询,然后删除数据库表***DbUtil.setParameter(driver, dbProtocol, dbName);DbUtil.CreateDbTable(CrtStudentTableSQL); //创建学生表DbUtil.UpdateDB(InitStudentTableSQL); //向学生表插入数据DbUtil.QueryInf(QuerySQL); //执行查询SQL,显示1条记录信息DbUtil.QueryInf(QuerySQL2); //执行查询SQL,显示所有记录DbUtil.DropTable(DropStudentTableSQL); //删除学生表}
} //演示创建数据库程序及简单操作,源代码文件DbUtil.java结束。
执行例程DbUtil可创建数据库。DbUtil.java源代码和例程运行结果:
一、使用Derby嵌入式数据库演示DbUtil
上面的演示程序,使用的是嵌入式的Derby数据库。在嵌入模式下,Derby 数据库引擎直接运行在应用程序的 JVM 中,数据库与应用程序共享同一个进程,是Derby数据库独有的应用模式。
嵌入式Derby数据库例程程序环境要求:需要Derby数据库的derby.jar。尽管在Java 1.6版本中Derby数据库中已集成了,但在某些高版本的JDK中没有包含,则需要到官网中下载相关程序包。并在程序的构建路径中导入derby.jar,导入后在构建路径(Java Build Path)的库(Libraries)属性页如下图所示。
图中的①是Derby的嵌入式JDBC驱动程序包。②是Derby的网络数据库模式的JDBC驱动程序包;③是MySQL的JDBC驱动程序包。
之所以会看到这么多JDBC驱动程序包,是因为我在做各种数据库环境的测试。如果你只测试其中的一种数据库环境,只需导入对应的即可。
源代码文件DbUtil.java中main()方法中默认提供的是嵌入式Derby数据库的测试代码。不同数据库环境创建的数据库在计算机中的位置可能完全不同,本例的嵌入式Derby数据库创建在D:盘的DB目录的子目录StudentDB,目录中包括表示数据库的所有数据文件,以及数据库日志文件等。嵌入式测试代码:
public static void main(String[] args) { //main方法开始:String driver = "org.apache.derby.jdbc.EmbeddedDriver" ; //Derby嵌入式数据库驱动String dbProtocol="jdbc:derby:" ;//数据库协议/***Derby嵌入式数据库,数据库名dbName,其中的 ";create=true"表示如果数据库* 不存在,就新建之。若用绝对路径数据库名,将在指定路径创建数据库,如本例所示。* 如用相对路径数据库名,则数据库创建在项目的工作目录下。 ***/String dbName = "D:\\DB\\StudentDB;create=true"; //***下面演示数据库表的创建、数据插入、查询,然后删除数据库表***DbUtil.setParameter(driver, dbProtocol, dbName);DbUtil.CreateDbTable(CrtStudentTableSQL); //创建学生表DbUtil.UpdateDB(InitStudentTableSQL); //向学生表插入数据DbUtil.QueryInf(QuerySQL); //执行查询SQL,显示1条记录信息DbUtil.QueryInf(QuerySQL2); //执行查询SQL,显示所有记录DbUtil.DropTable(DropStudentTableSQL); //删除学生表} //main方法结束。
说明: 在main()方法的最后一条语句删除学生表的目的是为了重复执行例程时不报错(DbUtil.DropTable(DropStudentTableSQL,user,passwd); //删除学生表)。上面这个嵌入式测试代码,没有使用数据库访问用户和密码。若想使用,也完全可以,程序后面部分略有不同,请参考网络数据库模式的代码。请自行修改调试。
二、使用Derby网络服务器模式数据库演示DbUtil
网络服务器模式,这是标准的数据库服务器/客户端模式,Derby 作为一个独立的数据库服务器运行,可以通过网络接受多个客户端的连接请求。
我笔记本电脑上使用的JDK版本是jdk1.8.0_171,已经包含了Derby数据库环境,Derby数据库相关的程序包都位于文件夹db内。
如果JDK中没有Derby数据库的程序包,就需要单独下载后,进行部署。
网络数据库模式的Derby数据库环境要求:
(1)部署网络模式的Derby数据库。如果JDK中没有Derby数据库相关包,就要下载一个,解压部署好(这一步相当于安装一个数据库管理系统)。我下载的是32位windows系统的derby数据库,它的版本号为10.14.2.0。
Derby数据库的程序包下载点: Derby数据库的程序包:Derby-10.14.2.0-lib.zip
我部署在D:盘,下图是部署后内部目录结构。相关的jar文件如derby.jar和derbyclient.jar等都在子目录lib中;子目录bin中有很多相关的批处理脚本如ij.bat和startNetworkServer.bat等。
说明: 子目录bin也是数据库的默认目录。如果创建数据库时使用相对路径,创建的数据库就位于此文件夹内,会有一个与数据库同名的子文件夹。我们在测试时,若要重建数据库,先把数据库网络服务关闭,然后再删除这个与数据库同名的子文件,就可重新创建同名的数据库。
(2)子目录bin有一些启动和关闭derby数据库的脚本,双击名为“startNetworkServer”或“startNetworkServer.bat”的windows批处理脚本可启动derby数据库服务器,(不同的windows版本启动方式略有不同)。
下图则是直接以管理员启动CDM后执行startNetworkServer.bat的执行效果图:
Derby数据库服务器的默认服务端口是“1527”,上图中也显示了这个端口信息。
可如下在CMD命令行窗口中输入命令“netstat -na | findstr :1527”,验证数据库服务是否存在。如下图查询出一行包含“1527”就是Derby网络数据库的服务进程。
(3)在程序的构建路径(Build Path)中要导入Derby的网络数据库服务器JDBC驱动程序包,本例中用到的是derbyclient.jar,构建路径的配置请参看前文嵌入式Derby数据库中的程序环境相关说明。Derby网络服务器数据库JDBC的驱动程序包为derbyclient.jar,驱动程序名有二个:“org.apache.derby.jdbc.Driver42”、“org.apache.derby.jdbc.ClientDriver”。这二个都是有效的。
(4)与MySQL数据库不同的是,Derby的网络服务器数据库不用设置字符集,就能正确打印显示汉字。
(5)在使用网络服务器数据库模式时,数据库名 dbName 的格式是”//”+服务器IP地址+”:”+数据库服务端口+”/”+带有路径的数据库名。其中服务器IP地址也可用服务器域名代替。如本例中的前半部分: “//localhost:1527/StudentDB”。localhost是本服务器的域名,相当于IP地址127.0.0.1表示本机(本服务器);如果数据库服务器与应用程序不在同一台电脑上则要使用实际的数据库服务器IP地址或域名。1527是Derby网络数据库的默认服务端口。本例的数据库名StudentDB,没带路径,相当于创建于当前目录,创建的数据库将在默认位置,即derby数据库工具ij所在的子目录bin中。
【例程15-4】使用工具类例程DbUtil创建网络服务器模式的数据库
网络服务器模式的Derby数据库演示程序与后文MySQL的几乎相同,只需要更新一下程序源码文件DbUtil.java中main()方法的前面几行定义字符串的代码,其它代码可共用,程序运行显示的查询结果与MySQL数据库中的也完全一样。直接修改DbUtil.java的main方法:
public static void main(String[] args) { //String driver = "org.apache.derby.jdbc.Driver42"; //亦可用String driver = "org.apache.derby.jdbc.ClientDriver"; //Derby网络服务器模式驱动String dbProtocol="jdbc:derby:" ;//数据库协议/***数据库名dbName,其中";create=true"表示如果数据库不存在,就新建之。***/String dbName = "//localhost:1527/StudentDB;create=true";String user = "root";String passwd = "psd234";
/***只需要更新以上几行代码。下面部分与MySQL完全相同***///***下面演示数据库表的创建、数据插入、查询,然后删除数据库表***DbUtil.setParameter(driver, dbProtocol, dbName);DbUtil.CreateDbTable(CrtStudentTableSQL,user,passwd); //创建学生表DbUtil.UpdateDB(InitStudentTableSQL,user,passwd); //向学生表插入数据DbUtil.QueryInf(QuerySQL); //执行查询SQL,显示1条记录信息DbUtil.QueryInf(QuerySQL2); //执行查询SQL,显示所有记录DbUtil.DropTable(DropStudentTableSQL,user,passwd); //删除学生表} //main方法结束。
说明: 运行演示Derby网络模式数据库创建时,必须确保Derby数据库网络服务已开启。开启方法,请参看上面的环境要求。
三、使用MySQL数据库演示DbUtil
MySQL数据库演示例程的环境要求:
1,安装并配置好MySQL数据库管理程序,并启动MySQL服务(具体请参考相关文档);
MySQL数据库下载点: MySQL安装包-社区版本-5.7.34.0ForWindows_x86_32-bit
2,创建一个测试用数据库。以Windows环境的MySQL 5.6为例,从开始菜单启动“MySQL 5.6 Command Line Client”,输入已配置的数据库root用户密码,将在命令行窗口出现mysql>提示符,然后我们可输入SQL命令创建数据库。下图创建了一个数据库StudentDB
3,为了让数据库支持显示中文,设置数据库StudentDB的字符集为gb2312
4,在程序的构建路径(Build Path)中要导入MySQL的JDBC驱动程序包,本例中用到的是mysql-connector-java-8.0.24.jar。(说明:MySQL的JDBC驱动名"com.mysql.jdbc.Driver"已经过时,新的写法是String driver = “com.mysql.cj.jdbc.Driver”; //MySQL数据库JDBC驱动)
如下图的③所示。下图中的①是Derby的嵌入式JDBC驱动程序包;②是Derby的网络数据库模式的JDBC驱动程序包。下图是我的开发环境,因为我同时测试这三种数据库模式,所以导入了三个JDBC驱动程序包。如果只测试MySQL数据库,只需导入MySQL的JDBC驱动程序包。
5,在使用数据库时可指定字符集以正确显示汉字,下面代码“?”及其后面部分即是。
String dbName = "//localhost:3306/StudentDB?useUnicode=true&characterEncoding=gb2312";
6,在网络服务器数据库模式,数据库名dbName的格式是”//”+服务器IP地址+”:”+数据库服务端口+”/”+数据库名。其中服务器IP地址也可用服务器域名代替。如本例中的前半部分: “//localhost:3306/StudentDB”。localhost表示本服务器的域名,相当于IP地址127.0.0.1表示本机(本服务器);如果数据库服务器与应用程序不在同一台电脑上则不能使用localhost表示数据库服务器。3306是MySQL数据库默认的服务端口。
【例程15-5】使用工具类例程DbUtil创建MySQL的数据库表
当数据库环境准备好后,如下修改DbUtil类的main方法,即可使用MySQL数据库进行测试演示:
public static void main(String[] args) { /***先设置MySQL数据库的各参数***/String driver = "com.mysql.cj.jdbc.Driver"; //MySQL数据库JDBC驱动String dbProtocol="jdbc:mysql:" ; //数据库协议String dbName = "//localhost:3306/StudentDB?useUnicode=true&characterEncoding=gb2312";String user = "root";String passwd ="psd234"; //数据库root用户的密码,你的环境可能不同/***下面演示,创建数据库表、插入记录、查询信息,然后删除数据库表***/DbUtil.setParameter(driver, dbProtocol, dbName); //初始化设置各参数DbUtil.CreateDbTable(CrtStudentTableSQL,user,passwd); //创建学生表DbUtil.UpdateDB(InitStudentTableSQL,user,passwd); //向学生表插入数据DbUtil.QueryInf(QuerySQL); //执行查询SQL,显示1条记录信息DbUtil.QueryInf(QuerySQL2); //执行查询SQL,显示所有记录DbUtil.DropTable(DropStudentTableSQL,user,passwd); //删除学生表} //main方法结束。
程序说明:此程序的静态方法可适用于各种数据库,不同数据库的差异很小。只是数据库的创建有些差异,MySQL数据库的创建最好使用命令行手工创建;Derby数据库则可以通过JDBC接口在程序中方便地自动创建。数据库表的创建、更新、查询,不同数据库差异很小。在查询并打印显示信息时,MySQL数据库还要考虑字符集的问题,因此本例中的数据库名dbName = “//localhost:3306/StudentDB?useUnicode=true&characterEncoding=gb2312”;
看上去有点复杂,后面部分“?useUnicode=true&characterEncoding=gb2312"”就是指定字符集,是为了正确显示中文信息。在main()方法的最后一条语句删除学生表的目的是为了重复执行例程时不报错。
DbUtil.DropTable(DropStudentTableSQL,user,passwd); //删除学生表
15.5.2 创建数据库例程CreateDB
本节将使用CreateDB例程来创建一个嵌入式Derby数据库环境,它将创建二个数据库表,作为后续例程的数据库环境。如果你想用CreateDB例程来创建网络服务器模式的Derby数据库或MySQL数据库环境则需要略作修改,方法与前文DbUtil的改造类似。
【例程15-6】创建数据库例程CreateDB
例程将创建一个学生数据库包含如下二个数据库表,这是二个表的定义需求:
创建数据库程序,源代码文件CreateDB.java如下:
package database;
import java.sql.*;
public class CreateDB {static final String driver = "org.apache.derby.jdbc.EmbeddedDriver" ;/***Derby嵌入式数据库,数据库名dbName变量,其中的 ";create=true"表示如果数据库
* 不存在,就新建之。如果使用绝对路径数据库名,将在指定路径创建数据库,如本例所示。* 如果使用相对路径的数据库名,则数据库创建在工作目录下。***/static final String dbName = "D:\\DB\\StudentDB;create=true"; //若不存在,则创建static final String dbProtocol="jdbc:derby:"; //数据库协议
private static Connection con = null ;/***创建学生基本信息表student.student的SQL语句脚本***/private static final String CrtStudentTableSQL = "CREATE TABLE student.student ( " +"studentID CHAR(6) PRIMARY KEY," +"name VARCHAR(8) NOT NULL," +"height REAL check(height>=0)," +"mealCardAmt DECIMAL(10,2) DEFAULT 2000 check(mealCardAmt>=0)," +"totalScore INT DEFAULT 0 check(totalScore>=0)," +"birthDay DATE )" ;/***创建课程成绩表student.courseScore的SQL语句脚本***/private static final String CrtCourseScoreTableSQL = "CREATE TABLE student.courseScore ( " +"studentID CHAR(6) NOT NULL," +"courseName VARCHAR(8)," +"courseScore INT, " +"FOREIGN KEY (studentID) REFERENCES student.student(studentID) )" ;/***删除学生基本信息表student.student的SQL语句脚本***/private static final String DropStudentTableSQL ="DROP TABLE student.student" ; /***删除课程成绩表student.courseScore的SQL语句脚本***/private static final String DropScoreTableSQL ="DROP TABLE student.courseScore" ; /***插入学生基本信息表student.student数据***/private static final String InitStudentTableSQL ="INSERT INTO student.student(studentID, name, height,birthDay, mealCardAmt) "+ " VALUES ('200001','高玉宝',1.75,'2002-05-08',2000)," +" ('200002','赵云',1.72,'2001-06-08',2000),"+" ('200003','李云龙',1.76,'2000-07-18',2000),"+" ('200004','钱江',1.70,'2001-10-08',2000),"+" ('200005','刘胡兰',1.56,'2002-06-01',2000)"; /***插入学生课程成绩表student.courseScore数据***/private static final String InitCourseScoreTableSQL ="INSERT INTO student.courseScore(studentID, courseName, courseScore) " +" VALUES ('200001','语文',80),('200001','数学',75),('200001','英文',88)," +" ('200002','语文',70),('200002','数学',95),('200002','英文',68)," +" ('200003','语文',60),('200003','数学',100),('200003','英文',58)," +" ('200004','语文',85),('200004','数学',78),('200004','英文',85)," +" ('200005','语文',72),('200005','数学',85),('200005','英文',80)";//建立数据库连接public static Connection GetConnection( String dbName ) throws SQLException {if ( con != null && !con.isClosed() ) return con; //连接不为空,且没关闭.else if (connectDb(dbName)) { return con; } //尝试建立数据库连接else {System.err.println("数据库不存在!数据连接失败。 ");return con;}}//根据参数,删除数据库表public static void DropTable(String dropTableSQL){ UpdateDB(dropTableSQL); }//根据建表参数,新建数据库表public static void CreateDbTable(String createTableSQL){ UpdateDB( createTableSQL ); }//根据sql参数,更新数据库表public static void UpdateDB(String sql){String url = dbProtocol + dbName ;try {if (con==null) { //如果数据库连接不存在,建立数据库连接Class.forName(driver) ; /*加载数据库驱动*///建立数据库连接con = DriverManager.getConnection(url);}Statement stmt = con.createStatement();stmt.executeUpdate(sql) ;stmt.close();}catch (SQLException se) {PrintSQLException(se) ;}catch(ClassNotFoundException e){System.err.println("JDBC Driver:" + driver + " not in CLASSPATH") ;}}//建立数据库连接,成功返回true,否则返回false。public static boolean connectDb(String dbName) {String url = dbProtocol + dbName;boolean rnflg = false ;try{Class.forName(driver) ; //加载驱动程序con = DriverManager.getConnection( url ); //联接数据库SQLWarning swarn = con.getWarnings(); if(swarn != null) PrintSQLWarning(swarn);rnflg = true ;} catch (SQLException se) {PrintSQLException(se) ;}catch(ClassNotFoundException e){System.err.println("JDBC Driver " + driver + " not found in CLASSPATH") ;}return(rnflg) ;}/***打印SQLException异常出错信息的方法***/public static void PrintSQLException(SQLException se) {while(se != null) {System.out.print("SQLException: State: " + se.getSQLState());System.out.println(" Severity: " + se.getErrorCode());System.out.println(se.getMessage()); se = se.getNextException();}} /***打印SQLWarning警告信息的方法***/public static void PrintSQLWarning(SQLWarning sw) {while(sw != null) {System.out.print("SQLWarning: State=" + sw.getSQLState()) ;System.out.println(" Severity = " + sw.getErrorCode()) ;System.out.println(sw.getMessage()); sw = sw.getNextWarning();}}public static void main(String[] args) { DropTable(DropScoreTableSQL); //删除成绩表DropTable(DropStudentTableSQL); //删除学生基本信息表System.out.print("首次执行删除数据库表时若有错误提示,请忽略,开始创数据库!\n");CreateDbTable(CrtStudentTableSQL); //创建“学生基本信息表”CreateDbTable(CrtCourseScoreTableSQL); //创建“课程成绩表”UpdateDB(InitStudentTableSQL); //插入学生基本信息表数据UpdateDB(InitCourseScoreTableSQL); //插入学生课程成绩表数据System.out.print("数据库Student创建成功!");}
} //创建数据库程序,源代码文件CreateDB.java结束。
准备数据库环境:执行程序CreateDB.java就可创建一个数据库。因为程序中已包含删除表的语句,可重复多次执行。但在首次执行时,由于没有数据库及相关数据库表,删除操作会报错,忽略报错即可。