Java教程是针对JDK 8编写的。本页中描述的示例和实践不利用后续版本引入的改进,并可能使用不再可用的技术。
有关Java SE 9及后续版本中更新的语言功能的摘要,请参见Java语言变更。
有关所有JDK版本的新功能、增强功能以及已删除或已弃用选项的信息,请参见JDK发行说明。
本页面描述了JDBC教程中使用的所有表以及如何创建它们:
COFFEES表存储了The Coffee Break可供销售的咖啡信息:
COF_NAME |
SUP_ID |
PRICE |
SALES |
TOTAL |
|---|---|---|---|---|
| 哥伦比亚咖啡 | 101 | 7.99 | 0 | 0 |
| 法式烘焙 | 49 | 8.99 | 0 | 0 |
| 浓缩咖啡 | 150 | 9.99 | 0 | 0 |
| 哥伦比亚无咖啡因 | 101 | 8.99 | 0 | 0 |
| 法式烘焙无咖啡因 | 49 | 9.99 | 0 | 0 |
以下描述了COFFEES表中的每个列:
COF_NAME:存储咖啡名称。具有SQL类型VARCHAR,最大长度为32个字符。由于每种类型的咖啡的名称不同,所以名称唯一地标识特定的咖啡,也作为主键。SUP_ID:存储标识咖啡供应商的编号。具有SQL类型INTEGER。它被定义为引用SUPPLIERS表中SUP_ID列的外键。因此,数据库管理系统将强制该列中的每个值与SUPPLIERS表中相应列中的值之一匹配。PRICE:存储每磅咖啡的成本。具有SQL类型FLOAT,因为它需要存储带有小数点的值。(请注意,货币值通常存储在SQL类型DECIMAL或NUMERIC中,但由于不同数据库管理系统之间的差异以及为了避免与早期版本的JDBC不兼容,教程使用更标准的类型FLOAT。)SALES:存储本周销售的咖啡磅数。具有SQL类型INTEGER。TOTAL:存储迄今为止销售的咖啡磅数。具有SQL类型INTEGER。SUPPLIERS表存储每个供应商的信息:
SUP_ID |
SUP_NAME |
STREET |
CITY |
STATE |
ZIP |
|---|---|---|---|---|---|
| 101 | Acme, Inc. | 99 Market Street | Groundsville | CA | 95199 |
| 49 | Superior Coffee | 1 Party Place | Mendocino | CA | 95460 |
| 150 | The High Ground | 100 Coffee Lane | Meadows | CA | 93966 |
以下描述了SUPPLIERS表中的每个列:
SUP_ID:存储识别咖啡供应商的编号。具有SQL类型为INTEGER的值。它是该表的主键。SUP_NAME:存储咖啡供应商的名称。STREET,CITY,STATE和ZIP:这些列存储咖啡供应商的地址。COF_INVENTORY表存储每个仓库中存储的咖啡数量的信息:
WAREHOUSE_ID |
COF_NAME |
SUP_ID |
QUAN |
DATE_VAL |
|---|---|---|---|---|
| 1234 | House_Blend | 49 | 0 | 2006_04_01 |
| 1234 | House_Blend_Decaf | 49 | 0 | 2006_04_01 |
| 1234 | Colombian | 101 | 0 | 2006_04_01 |
| 1234 | French_Roast | 49 | 0 | 2006_04_01 |
| 1234 | Espresso | 150 | 0 | 2006_04_01 |
| 1234 | Colombian_Decaf | 101 | 0 | 2006_04_01 |
下面描述了COF_INVENTORY表中的每一列:
WAREHOUSE_ID:存储标识仓库的数字。COF_NAME:存储特定类型咖啡的名称。SUP_ID:存储标识供应商的数字。QUAN:存储表示可用商品数量的数字。DATE:存储表示最后更新行的时间戳值。MERCH_INVENTORY表存储了非咖啡商品库存的信息:
ITEM_ID |
ITEM_NAME |
SUP_ID |
QUAN |
DATE |
|---|---|---|---|---|
| 00001234 | 大杯 | 00456 | 28 | 2006_04_01 |
| 00001235 | 小杯 | 00456 | 36 | 2006_04_01 |
| 00001236 | 茶碟 | 00456 | 64 | 2006_04_01 |
| 00001287 | 咖啡壶 | 00456 | 12 | 2006_04_01 |
| 00006931 | 咖啡壶 | 00927 | 3 | 2006_04_01 |
| 00006935 | 隔热垫 | 00927 | 88 | 2006_04_01 |
| 00006977 | 餐巾纸 | 00927 | 108 | 2006_04_01 |
| 00006979 | 毛巾 | 00927 | 24 | 2006_04_01 |
| 00004488 | 咖啡机 | 08732 | 5 | 2006_04_01 |
| 00004490 | 咖啡研磨机 | 08732 | 9 | 2006_04_01 |
| 00004495 | 意式咖啡机 | 08732 | 4 | 2006_04_01 |
| 00006914 | 烹饪书 | 00927 | 12 | 2006_04_01 |
下面描述了MERCH_INVENTORY表中的每个列:
ITEM_ID:存储标识商品的数字。ITEM_NAME:存储商品的名称。SUP_ID:存储标识供应商的数字。QUAN:存储表示该商品可用数量的数字。DATE:存储时间戳值,表示该行最后更新的时间。COFFEE_HOUSES表存储咖啡店的位置:
STORE_ID |
CITY |
COFFEE |
MERCH |
TOTAL |
|---|---|---|---|---|
| 10023 | Mendocino | 3450 | 2005 | 5455 |
| 33002 | Seattle | 4699 | 3109 | 7808 |
| 10040 | 旧金山 | 5386 | 2841 | 8227 |
| 32001 | 波特兰 | 3147 | 3579 | 6726 |
| 10042 | 旧金山 | 2863 | 1874 | 4710 |
| 10024 | 萨克拉门托 | 1987 | 2341 | 4328 |
| 10039 | 卡梅尔 | 2691 | 1121 | 3812 |
| 10041 | 洛杉矶 | 1533 | 1007 | 2540 |
| 33005 | 奥林匹亚 | 2733 | 1550 | 4283 |
| 33010 | 西雅图 | 3210 | 2177 | 5387 |
| 10035 | 旧金山 | 1922 | 1056 | 2978 |
| 10037 | 洛杉矶 | 2143 | 1876 | 4019 |
| 10034 | 圣何塞 | 1234 | 1032 | 2266 |
| 32004 | 尤金 | 1356 | 1112 | 2468 |
以下描述了COFFEE_HOUSES表中的每一列:
STORE_ID:存储标识咖啡馆的数字。它表示咖啡馆所在的州,其中包括咖啡馆位于加利福尼亚州的州。例如,以10开头的值表示州是加利福尼亚州。以32开头的STORE_ID值表示俄勒冈州,以33开头的值表示华盛顿州。CITY:存储咖啡馆所在城市的名称。COFFEE:存储表示咖啡销量的数字。MERCH:存储表示商品销量的数字。TOTAL:存储表示咖啡和商品总销量的数字。DATA_REPOSITORY表存储引用The Coffee Break感兴趣的文档和其他数据的URL。脚本populate_tables.sql不会向此表添加任何数据。以下描述了此表中的每一列:
DOCUMENT_NAME:存储标识URL的字符串。URL:存储URL。您可以使用Apache Ant或JDBC API创建表。
要创建与教程示例代码一起使用的表,请在目录<JDBC教程目录>中运行以下命令:
ant setup
此命令运行多个Ant目标,包括以下目标build-tables(来自build.xml文件):
<target name="build-tables"
description="创建数据库表">
<sql
driver="${DB.DRIVER}"
url="${DB.URL}"
userid="${DB.USER}"
password="${DB.PASSWORD}"
classpathref="CLASSPATH"
delimiter="${DB.DELIMITER}"
autocommit="false" onerror="abort">
<transaction src=
"./sql/${DB.VENDOR}/create-tables.sql"/>
</sql>
</target>
示例为以下sql Ant任务参数指定了值:
| 参数 | 描述 |
|---|---|
driver |
您的JDBC驱动的完全限定类名。此示例使用org.apache.derby.jdbc.EmbeddedDriver用于Java DB,以及com.mysql.cj.jdbc.Driver用于MySQL Connector/J。 |
url |
数据库连接URL,您的DBMS JDBC驱动程序用于连接数据库。 |
userid |
您DBMS中一个有效用户的名称。 |
password |
userid中指定的用户的密码。 |
classpathref |
包含driver指定的类的JAR文件的完整路径名 |
delimiter |
用于分隔SQL语句的字符串或字符。此示例使用分号 (;)。 |
autocommit |
布尔值;如果设置为false,则所有SQL语句将作为一个事务执行。 |
onerror |
当语句失败时执行的操作;可能的值为continue、stop和abort。值abort指定如果发生错误,则事务将被中止。 |
示例将这些参数的值存储在一个单独的文件中。构建文件build.xml使用import任务检索这些值:
<import file="${ANTPROPERTIES}"/>
transaction元素指定包含要执行的SQL语句的文件。文件create-tables.sql包含创建本页上描述的所有表的SQL语句。例如,以下摘录自该文件的内容创建了SUPPLIERS和COFFEES两个表:
create table SUPPLIERS
(SUP_ID integer NOT NULL,
SUP_NAME varchar(40) NOT NULL,
STREET varchar(40) NOT NULL,
CITY varchar(20) NOT NULL,
STATE char(2) NOT NULL,
ZIP char(5),
PRIMARY KEY (SUP_ID));
create table COFFEES
(COF_NAME varchar(32) NOT NULL,
SUP_ID int NOT NULL,
PRICE numeric(10,2) NOT NULL,
SALES integer NOT NULL,
TOTAL integer NOT NULL,
PRIMARY KEY (COF_NAME),
FOREIGN KEY (SUP_ID)
REFERENCES SUPPLIERS (SUP_ID));
注意:文件build.xml还包含另一个名为drop-tables的目标,用于删除教程中使用的表。在运行build-tables目标之前,setup目标将运行drop-tables。
下面的方法SuppliersTable.createTable创建了SUPPLIERS表格:
public void createTable() throws SQLException {
String createString =
"create table SUPPLIERS " + "(SUP_ID integer NOT NULL, " +
"SUP_NAME varchar(40) NOT NULL, " + "STREET varchar(40) NOT NULL, " +
"CITY varchar(20) NOT NULL, " + "STATE char(2) NOT NULL, " +
"ZIP char(5), " + "PRIMARY KEY (SUP_ID))";
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate(createString);
} catch (SQLException e) {
JDBCTutorialUtilities.printSQLException(e);
}
}
下面的方法CoffeesTable.createTable创建了COFFEES表格:
public void createTable() throws SQLException {
String createString =
"create table COFFEES " + "(COF_NAME varchar(32) NOT NULL, " +
"SUP_ID int NOT NULL, " + "PRICE numeric(10,2) NOT NULL, " +
"SALES integer NOT NULL, " + "TOTAL integer NOT NULL, " +
"PRIMARY KEY (COF_NAME), " +
"FOREIGN KEY (SUP_ID) REFERENCES SUPPLIERS (SUP_ID))";
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate(createString);
} catch (SQLException e) {
JDBCTutorialUtilities.printSQLException(e);
}
}
在这两个方法中,con是一个Connection对象,dbName是你要创建表格的数据库的名称。
要执行SQL查询,例如String createString指定的查询,需要使用Statement对象。要创建Statement对象,请从现有的Connection对象调用方法Connection.createStatement。要执行SQL查询,请调用方法Statement.executeUpdate。
所有的Statement对象在创建它们的连接关闭时会被关闭。但是,最好的编码实践是在使用完Statement对象后显式关闭它们。这可以立即释放语句使用的任何外部资源。通过调用方法Statement.close来关闭语句。将此语句放在finally块中,以确保即使程序流因抛出异常(如SQLException)而中断,它也会关闭。
注意:在创建SUPPLIERS表之前,您必须创建COFFEES表,因为COFFEES包含一个外键SUP_ID,它引用了SUPPLIERS表。
同样地,您可以使用Apache Ant或JDBC API向表格中插入数据。
除了创建本教程中使用的表格之外,命令ant setup还会填充这些表格。该命令运行Ant目标populate-tables,该目标运行SQL脚本populate-tables.sql。
以下是从populate-tables.sql中提取的填充SUPPLIERS和COFFEES表的摘录:
insert into SUPPLIERS values(
49, 'Superior Coffee', '1 Party Place',
'Mendocino', 'CA', '95460');
insert into SUPPLIERS values(
101, 'Acme, Inc.', '99 Market Street',
'Groundsville', 'CA', '95199');
insert into SUPPLIERS values(
150, 'The High Ground',
'100 Coffee Lane', 'Meadows', 'CA', '93966');
insert into COFFEES values(
'Colombian', 00101, 7.99, 0, 0);
insert into COFFEES values(
'French_Roast', 00049, 8.99, 0, 0);
insert into COFFEES values(
'Espresso', 00150, 9.99, 0, 0);
insert into COFFEES values(
'Colombian_Decaf', 00101, 8.99, 0, 0);
insert into COFFEES values(
'French_Roast_Decaf', 00049, 9.99, 0, 0);
下面的方法SuppliersTable.populateTable向表格中插入数据:
public void populateTable() throws SQLException {
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate("insert into SUPPLIERS " +
"values(49, 'Superior Coffee', '1 Party Place', " +
"'Mendocino', 'CA', '95460')");
stmt.executeUpdate("insert into SUPPLIERS " +
"values(101, 'Acme, Inc.', '99 Market Street', " +
"'Groundsville', 'CA', '95199')");
stmt.executeUpdate("insert into SUPPLIERS " +
"values(150, 'The High Ground', '100 Coffee Lane', " +
"'Meadows', 'CA', '93966')");
} catch (SQLException e) {
JDBCTutorialUtilities.printSQLException(e);
}
}
下面的方法CoffeesTable.populateTable向表格中插入数据:
public void populateTable() throws SQLException {
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate("insert into COFFEES " +
"values('Colombian', 00101, 7.99, 0, 0)");
stmt.executeUpdate("insert into COFFEES " +
"values('French_Roast', 00049, 8.99, 0, 0)");
stmt.executeUpdate("insert into COFFEES " +
"values('Espresso', 00150, 9.99, 0, 0)");
stmt.executeUpdate("insert into COFFEES " +
"values('Colombian_Decaf', 00101, 8.99, 0, 0)");
stmt.executeUpdate("insert into COFFEES " +
"values('French_Roast_Decaf', 00049, 9.99, 0, 0)");
} catch (SQLException e) {
JDBCTutorialUtilities.printSQLException(e);
}
}