目录
第1关 数据库连接与数据库实例创建
一、数据库实例
MySQL 是一个客户机-服务器(Client/Server)类型的数据库管理系统。
JDBC(Java Data Base Connectivity)是一种标准的基于 Java 语言的数据库访问接口,目前几乎所有数据库都提供 JDBC 接口,MySQL 也支持 Java 应用程序通过该接口对数据库进行访问和处理。
在 Java 应用程序中通过 JDBC 连接并访问 MySQL 数据库通常需要以下步骤:
(1) 导入 JDBC 包;
(2) 注册 JDBC 驱动程序;
(3) 指定目标数据库,包括主机名、端口号、数据 库用户名、密码等;
(4) 创建连接对象,建立与数据库的连接;
(5) 创建执行 SQL 语句的对象实例 Statement;
(6) 编写 SQL 语句;
(7) 执行 SQL 语句。
在首次连接到 MySQL 时,仅仅是连接到了相应的服务,并没有打开任何数据库实例。如果要存储和管理数据,我们首先需要创建自己的数据库实例,其基本语法如下:create database
+ 数据库实例名称
二、代码
在给定 MySQL 数据库中创建一个数据库实例,即实现step1/MySQLJDBC.java
的createDatabaseInstance(Connection connection, String instanceName)
函数:
package step1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class MySQLWithJDBC {
//指定数据库驱动
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
//设定本地数据库的URL,并指定编码方式为UTF-8且关闭SSL连接
static final String DB_URL = "jdbc:mysql:///?useUnicode=true&characterEncoding=utf-8&useSSL=false";
// 指定数据库的用户名和密码
static final String USER = "root";
static final String PASS = "123123";
// 创建数据库实例
public void createDatabaseInstance(Connection connection, String databaseName){
Statement stmt = null;
// 请补全下面创建数据库实例的SQL语句sqlScript
String sqlScript = "create database " + databaseName;
try {
stmt = (Statement) connection.createStatement();
stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 建立与指定数据库的连接,并返回该连接
public Connection getConnection(String jdbc_driver, String db_url, String db_user, String db_passwd) {
Connection connection = null;
// 注册JDBC驱动
try {
Class.forName(jdbc_driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
// 创建于指定数据库的连接
connection = DriverManager.getConnection(db_url, db_user, db_passwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//删除数据库
public void dropDatabase(Connection connection, String databaseName){
Statement stmt = null;
String sqlScript = "drop database if exists " + databaseName;
try {
stmt = (Statement) connection.createStatement();
stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 获取数据库中已经存在的数据库实例
public ResultSet getExistDB(Connection connection, String databaseName) throws SQLException
{
ResultSet resultSet = null;
Statement stmt = null;
/******* Begin ******/
String sqlScript = "SELECT * FROM information_schema.SCHEMATA where SCHEMA_NAME=\"" + databaseName + "\"";
/******* End ******/
try {
stmt = (Statement) connection.createStatement();
resultSet = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return resultSet;
}
}
第2关 数据表的创建
一、数据表
在数据库中,数据是以表(Table)为单位进行组织的。数据表由列(column)组成,通过列名和数据类型等来指定列的属性,数据表的每一列存储了表中某一类特定的信息,如学号或者姓名等。列(column)也可以叫做数据表的一个字段,列(column)的名字也叫做字段名;表中的数据是按行(row)进行存储的,每一行代表一条数据记录。
CREATE 是 SQL 语法中的建数据库/建表的关键词,基本的 CREATE 语句有两部分组成:
- 要创建的数据表的表名
- 数据表的列名及数据类型
建立数据库实例之后,我们还需要在其中创建相应的数据表才能进行数据的存储和处理。创建数据表的 SQL 语句基本语法如下:CREATE TABLE
+ 表名
(
列名a 数据类型(数据长度),
列名b 数据类型(数据长度),
列名c 数据类型(数据长度),
);
其中,数据长度可以不进行限定,此时会取默认值。
MySQL 常用的数据类型如下表所示:
关键字 | 长度 | 说明 |
---|---|---|
INT | 4字节 | 整数,范围(-2147483648~2147483647) |
CHAR(n) | 0~255字符 | 固定长度,最多255个字符 |
VARCHAR(n) | 0~255字符 | 可变长度,最多65535个字符 |
TEXT | 0~65535字符 | 可变长度,最多65535个字符 |
YEAR | 1字节 | 年份值 |
二、代码
本关任务是在指定数据库中创建数据表,即实现step2/CreateTable.java的createTable(Connection connection, String tableName, TableInfo tableInfo)
方法,该方法的具体定义如下:
/**
* 在指定数据库中创建以tableName命名的表
* @param connection mysql连接对象
* @param tableName 数据表名
* @param tableInfo 存放表的字段及其属性的二维数组,如tableInfo[k][0]代表第k个字段名,tableInfo[k][1]代表第k个字段的属性
*/
public void createTable(Connection connection, String tableName,String[][] tableInfo){
Statement stmt = null;
//请在此处补全创建表的SQL语句,不要改动其他代码
/******* Begin ******/
String sqlScript = "";
/******* End ******/
try {
//创建查询语句对象
stmt = connection.createStatement();
//执行查询
stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackT\frace();
}
}
其中,tableInfor
是一个字符串类型的二元数组,存储了数据表涉及的所有列的列名及对应的数据类型。以图书表为例,其对应的tableInfor
数组如下表所示:
id | INT |
---|---|
title | VARCHAR |
author | CHAR |
... | ... |
参数 tableName 为创建的具体数据表名。 |
测试说明
package step2;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class CreateTable {
// 设定JDBC驱动以及本地数据库的URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql:///bookstore?useUnicode=true&characterEncoding=utf-8&useSSL=false";
// 指定数据库的用户名和密码
static final String USER = "root";
static final String PASS = "123123";
/**
* 在指定数据库中创建以tableName命名的表
* @param connection mysql连接对象
* @param tableName 数据表名
* @param tableInfo 存放表的字段及其属性的二维数组,如tableInfo[k][0]代表第k个字段名,tableInfo[k][1]代表第k个字段的属性
*/
public void createTable(Connection connection, String tableName,String[][] tableInfo){
Statement stmt = null;
//请在此处补全创建表的SQL语句,不要改动其他代码
/******* Begin ******/
String sqlScript = "create table " + tableName + "(\n";
for(int k=0; k<tableInfo.length; k++){
if(tableInfo[k][0].equals(""))
break;
sqlScript = sqlScript + tableInfo[k][0] + " " + tableInfo[k][1] + ",\n";
}
sqlScript = sqlScript.substring(0, sqlScript.length()-2);
sqlScript = sqlScript + ")";
/******* End ******/
try {
//创建查询语句对象
stmt = connection.createStatement();
//执行查询
stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 建立与指定数据库的连接,并返回该连接
public Connection getConnection(String jdbc_driver, String db_url, String db_user, String db_passwd) {
Connection connection = null;
//注册JDBC驱动
try {
Class.forName(jdbc_driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//创建于指定数据库的连接
try {
connection = (Connection) DriverManager.getConnection(db_url, db_user, db_passwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//获取databaseNames数据库中的tablenName表
public ResultSet getExistTable(Connection conn,String databaseName,String tableName) {
ResultSet resultSet = null;
Statement stmt = null;
String sqlScript = "select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=\'" +databaseName +
"\' and TABLE_NAME=\'" + tableName + "\'";
try {
stmt = (Statement) conn.createStatement();
resultSet = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return resultSet;
}
//加载sql脚本
List<String> loadSql(String sqlFile) throws Exception {
List<String> sqlList = new ArrayList<String>();
try {
InputStream sqlFileIn = new FileInputStream(sqlFile);
StringBuffer sqlSb = new StringBuffer();
byte[] buff = new byte[1024];
int byteRead = 0;
while ((byteRead = sqlFileIn.read(buff)) != -1) {
sqlSb.append(new String(buff, 0, byteRead));
} // Windows 下换行是 \r\n, Linux 下是 \n
String[] sqlArr = sqlSb.toString().split("(;\\s*\\r\\n)(;\\s*\\n)");
for (int i = 0; i < sqlArr.length; i++) {
String sql = sqlArr[i].replaceAll("--.*", "").trim();
if (!sql.equals("")) {
sqlList.add(sql);
}
}
return sqlList;
} catch (Exception ex) {
throw new Exception(ex.getMessage());
}
}
}
第3关 数据查询操作
SELECT
数据查询是数据库最基础也是最常用的操作。SELECT是 SQL 语法中的查询关键词,在此基础上可以结合需要使用多种不同的表达方式来进行查询。
基本的 SELECT 语句有三部分组成:
- 需要返回的数据列名;
- 需要查询的数据表名;
- 查询过滤条件。
数据查询的 SQL 语句基本语法有以下三种:
(1) SELECT 列名X, 列名Y, 列名Z FROM 表名;
(2) SELECT * FROM 表名;
(3) SELECT * FROM 表名 WHERE 过滤条件;
其中:
- 第(1)种方式是从指定数据表中检索多列,具体由“列名X,列名Y,列名Z”指定;
- 第(2)种方式是从指定数据表中检索所有列数据,“ * ”是通配符,表示所有列;
- 第(3)种方式是从指定数据表中检索符合过滤条件的数据记录的所有列,其中,WHERE 是表示过滤条件的关键词,表示仅对表中数据的某个子集进行查询或者其他操作。常见的过滤表达式如下表所示:
本关任务
本关任务是从 book 表中查询图书名为指定名称的所有图书的出版社即 publisher(出版社需去重),并以字符串数组返回查询结果,即实现step3/QueryRecord.java
中的queryPublisherByBookName(Connection connection, String bookName)
方法。该方法定义如下:
/**
*在tableName中查询出书名为bookName的出版社
* @param Connection 数据库连接
* @param tableName 数据表名
* @param bookName 书名
*/
public ResultSet queryPublisherByBookName(Connection connection, String tableName,String bookName)
{
Statement stmt = null;
ResultSet result = null;
//请在此处补全查询数据的SQL语句,不要改动其他代码
/******* Begin ******/
String sqlScript = "";
/******* End ******/
try {
stmt = connection.createStatement();
result = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
package step3;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class QueryRecord {
// 设定JDBC驱动以及本地数据库的URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql:///bookstore?useUnicode=true&characterEncoding=utf-8&useSSL=false";
// 指定数据库的用户名和密码
static final String USER = "root";
static final String PASS = "123123";
/**
*在tableName中查询出书名为bookName的出版社
* @param Connection 数据库连接
* @param tableName 数据表名
* @param bookName 书名
*/
public ResultSet queryPublisherByBookName(Connection connection, String tableName,String bookName){
Statement stmt = null;
ResultSet result = null;
// 请补全下面的查询表的SQL查询命令
String sqlScript = "select distinct(publisher) from " + tableName + " where title = \'" + bookName + "\'";
try {
stmt = connection.createStatement();
result = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
// 建立与指定数据库的连接,并返回该连接
public Connection getConnection(String jdbc_driver, String db_url, String db_user, String db_passwd) {
Connection connection = null;
//注册JDBC驱动
try {
Class.forName(jdbc_driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//创建于指定数据库的连接
try {
connection = (Connection) DriverManager.getConnection(db_url, db_user, db_passwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
}
第4关 数据库的插入操作
INSERT INTO … VALUES
数据表的数据是按行存储的,每一行对应一条数据记录。一个数据表由一条或是多条记录组成,没有记录的表称为空表。
INSERT INTO … VALUES是SQL语法中的插入关键词,基本的INSERT语句有部分组成:
- 要插入数据的表
- 要插入的列名(可选)
- 要插入的数据
向数据表中插入数据的SQL语句基本语法如下:
(1) INSERT INTO表名(列名a, 列名b, 列名c)VALUES(值1,值2,值3);
或者
(2) INSERT INTO表名(列名a, 列名c)VALUES(值1,值3);
或者
(3) INSERT INTO表名VALUES(值1,值2,值3);
或者
(4) INSERT INTO表名(列名a,列名b,列名c)VALUES(值11,值12,值13), (值21,值22,值23), (值31,值32,值33),…,(值n1,值n2,值n3);
其中,第(1)种写法适合任何场景;第(2)中写法适合数据表某些字段允许为空且实际数据对应字段的值为空的情况;第(3)种写法适合实际数据所有字段的值都不为空的情况;第(4)种写法是在一条SQL语句中添加多条数据记录,每一条数据记录用括号括起来,数据记录之间用逗号隔开。
其中,第(1)种写法适合任何场景;第(2)中写法适合数据表某些字段允许为空且实际数据对应字段的值为空的情况;第(3)种写法适合实际数据所有字段的值都不为空的情况;第(4)种写法是在一条SQL语句中添加多条数据记录,每一条数据记录用括号括起来,数据记录之间用逗号隔开。
本关任务
本关的任务是编程实现在book表中插入图书记录,即实现step4/InsertTable.java
的InsertRecord(Connection connection, int id, String title, String author, String publisher, int year)
方法。该方法将在book表中插入由给定参数对应的数据记录,具体定义如下:
/**
* 向指定表中插入数据
* @param connection 数据库连接对象
* @param id 记录的id
* @param title 书名
* @param author 作者
* @param publisher 出版社
* @param year 出版年份
*/
public void InsertRecord(Connection connection, int id, String title, String author, String publisher, int year){
Statement stmt = null;
//请在此处补全向指定表插入数据的SQL语句,不要改动其他代码
/******* Begin ******/
String sqlScript = "";
/******* End ******/
try {
stmt = connection.createStatement();
stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackT\frace();
}
}
package step4;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class InsertTable {
// 设定JDBC驱动以及本地数据库的URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost/bookstore?useUnicode=true&characterEncoding=utf-8&useSSL=false";
// 指定数据库的用户名和密码
static final String USER = "root";
static final String PASS = "123123";
/**
* 向指定表中插入数据
* @param connection 数据库连接对象
* @param id 记录的id
* @param title 书名
* @param author 作者
* @param publisher 出版社
* @param year 出版年份
*/
public void InsertRecord(Connection connection, int id, String title, String author, String publisher, int year){
//在此添加插入数据的操作
Statement stmt = null;
String sqlScript = "Insert into book(id,title,author,publisher,publishYear)" + " values" + "(" + id +"," +"\'" + title+ "\',\'" + author + "\',\'" + publisher + "\',\'" + year + "\')";
try {
stmt = connection.createStatement();
stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 建立与指定数据库的连接,并返回该连接
public Connection getConnection(String jdbc_driver, String db_url, String db_user, String db_passwd) {
Connection connection = null;
//注册JDBC驱动
try {
Class.forName(jdbc_driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//创建于指定数据库的连接
try {
connection = (Connection) DriverManager.getConnection(db_url, db_user, db_passwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public ResultSet queryDB(Connection connection,String tableName) {
ResultSet result = null;
Statement stmt = null;
String sqlScript = "select * from " + tableName + " order by id desc";
try {
stmt = connection.createStatement();
result = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
List<String> loadSql(String sqlFile) throws Exception {
List<String> sqlList = new ArrayList<String>();
try {
InputStream sqlFileIn = new FileInputStream(sqlFile);
StringBuffer sqlSb = new StringBuffer();
byte[] buff = new byte[1024];
int byteRead = 0;
while ((byteRead = sqlFileIn.read(buff)) != -1) {
sqlSb.append(new String(buff, 0, byteRead));
} // Windows 下换行是 \r\n, Linux 下是 \n
String[] sqlArr = sqlSb.toString().split("(;\\s*\\r\\n)(;\\s*\\n)");
for (int i = 0; i < sqlArr.length; i++) {
String sql = sqlArr[i].replaceAll("--.*", "").trim();
if (!sql.equals("")) {
sqlList.add(sql);
}
}
return sqlList;
} catch (Exception ex) {
throw new Exception(ex.getMessage());
}
}
}
第5关 数据表的删除操作
一、数据表记录的删除
数据表记录的删除是数据库的基本操作之一。DELETE 是 SQL 语法中的删除关键词,基本的 DELETE 语句有两部分组成:
- 要删除的表;
- 确定需要删除的过滤条件。
从数据表中删除记录的 SQL 语句基本语法有以下两种:
(1) DELETE FROM 表名;
(2) DELETE FROM 表名 WHERE 过滤条件。
其中,第 (1) 种是不带条件的删除操作,会清除相应数据表中的所有记录;第 (2) 种是带过滤条件的删除操作,仅从指定表中删除符合条件的那些数据记录。
二、本关任务
本关的任务是编程实现从 book 表中删除作者名为特定作者的所有图书,即实现step5/DeleteRecord.java
的deleteRecordByAuthor(Connection connection, String author)
方法。
该方法具体定义如下:
/**
* 根据作者名删除记录
* @param connection 数据库连接
* @param tableName 数据表名
* @param author 作者名
*/
public int deleteRecordByAuthor(Connection connection, String tableName,String author)
{
Statement stmt = null;
int updatedNum = 0;
//请在此处补全删除数据库记录的SQL语句,不要改动其他代码
/******* Begin ******/
String sqlScript = "";
/******* End ******/
try {
stmt = connection.createStatement();
updatedNum = stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackT\frace();
}
//返回成功删除的条数
return updatedNum;
}
package step5;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DeleteRecord {
// 设定JDBC驱动以及本地数据库的URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql:///bookstore?useUnicode=true&characterEncoding=utf-8&useSSL=false";
// 指定数据库的用户名和密码
static final String USER = "root";
static final String PASS = "123123";
/**
* 根据作者名删除某条记录
* @param connection 数据库连接
* @param tableName 数据表名
* @param author 作者名
*/
public int deleteRecordByAuthor(Connection connection, String tableName,String author){
// 请在此处添加数据库删除记录的实现代码
Statement stmt = null;
int updatedNum = 0;
// 删除数据表中数据的SQL语句
String sqlScript = "delete from " + tableName + " where author = \'" + author +"\'";
try {
stmt = connection.createStatement();
updatedNum = stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return updatedNum;
}
// 建立与指定数据库的连接,并返回该连接
public Connection getConnection(String jdbc_driver, String db_url, String db_user, String db_passwd) {
Connection connection = null;
//注册JDBC驱动
try {
Class.forName(jdbc_driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//创建于指定数据库的连接
try {
connection = (Connection) DriverManager.getConnection(db_url, db_user, db_passwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//查询数据库
public ResultSet queryDB(Connection connection,String tableName) {
ResultSet result = null;
Statement stmt = null;
String sqlScript = "select * from " + tableName + " order by id desc";
try {
stmt = connection.createStatement();
result = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
}
第6关 数据表的更新操作
一、数据更新
数据更新操作是指对数据表中特定记录的特定字段的值进行更新。UPDATE 是 SQL 语法中数据更新的关键词。基本的 UPDATE 语句有三部分组成:
- 要更新的表;
- 需要更新的列名及他们的新值;
- 确定需要更新的过滤条件。
基本语法如下:
``UPDATE 表名 SET 列名a=新值1,列名b=新值2 WHERE 过滤条件
基于该语法可以同时更新一张表中的一个或多个列,同时更新多个列时列之间用逗号隔开。特别要注意的是,如果不使用 WHERE 进行限定,则会对整个表中的数据记录进行更新。
二、代码
本关任务是编程实现对 book 表中指定书名的所有图书的出版社进行更新操作,即实现step6/UpdateRecord.java
中的updatePublisherByTitle(Connection connection, String title, String publisher)
方法。该方法具体定义如下:
/**
* 更新数据库表中的数据
* @param connection 数据库连接
* @param tableName 数据库表名
* @param title 书名
* @param publisher 出版社
*/
public int updatePublisherByTitle(Connection connection,String tableName, String title, String publisher){
Statement stmt = null;
int updatedNum=0;
//请在此处补全创建更新数据库记录的SQL语句,不要改动其他代码
/******* Begin ******/
String sqlScript = "";
/******* End ******/
try {
stmt = connection.createStatement();
updatedNum = stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackT\frace();
}
return updatedNum;
}
package step6;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.io.*;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.types.*;
public class UpdateRecord {
// 设定JDBC驱动以及本地数据库的URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql:///bookstore?useUnicode=true&characterEncoding=utf-8&useSSL=false";
// 指定数据库的用户名和密码
static final String USER = "root";
static final String PASS = "123123";
/**
* 更新数据库表中的数据
* @param connection 数据库连接
* @param tableName 数据库表名
* @param title 书名
* @param publisher 出版社
*/
public int updatePublisherByTitle(Connection connection,String tableName, String title, String publisher){
//请在此处实现数据更新功能
Statement stmt = null;
int updatedNum=0;
String sqlScript = "update " + tableName + " set publisher=\'" + publisher + "\'where title=\'" + title + "\'";
try {
stmt = connection.createStatement();
updatedNum = stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return updatedNum;
}
// 建立与指定数据库的连接,并返回该连接
public Connection getConnection(String jdbc_driver, String db_url, String db_user, String db_passwd) {
Connection connection = null;
//注册JDBC驱动
try {
Class.forName(jdbc_driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//创建于指定数据库的连接
try {
connection = (Connection) DriverManager.getConnection(db_url, db_user, db_passwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//查询数据库
public ResultSet queryDB(Connection connection,String tableName) {
ResultSet result = null;
Statement stmt = null;
String sqlScript = "select * from " + tableName + " order by id desc";
try {
stmt = connection.createStatement();
result = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
}
第7关 数据库的应用
在数据库设计中,数据表结构的设计对数据库系统性能等方面的影响很大。完全相同的一份数据,可以设计完全不同的数据表来进行存储,所占用的存储空间及查询性能等都是不一样的。为此,可以针对特定数据的特点,对给定的数据表进行重新设计,并将原始数据转存到新的数据表中存储。
以 book 表为例,下表是 book 表初始的数据表:
id | title | author | publisher | publisherYear |
---|---|---|---|---|
1004 | 平凡的世界 | 人民文学出版社 | ||
1208 | 钱钟书 |
如果 book 表中有大量数据行的某些列为空,则可以将其转换为下表 transformedBook 的数据表以节省存储空间:
id | column_name | value |
---|---|---|
1004 | title | 平凡的世界 |
1004 | publisher | 人民文学出版社 |
1208 | author | 钱钟书 |
其中,id 含义不变,column_name 表示列名,value 表示 id 对应数据在该列的值。
本关任务
本关任务是基于前面学习的数据表创建、数据查询、数据插入等操作,在 bookStore 数据库实例中创建一个名为 transformedBook 的表,并将 book 表中非空的数据存入 transformedBook 表中。
本关需要实现step7/TableTransfer.java
的tableTransformation(Connection connection)
方法,该方法的具体定义如下:
/**
* 转换数据表
* @param connection 数据库连接对象
* @param tableName 原始数据表名
*/
public void transferTable(Connection connection, String tableName) throws SQLException{
//请在此处补全转换表的SQL语句,不要改动其他代码
/******* Begin ******/
/******* End ******/
}
测试说明
代码补充,具体任务如下:
package step6;
public class TransferTableTest {
public static void main(String args[]) throws SQLException {
TransferTable transferTable = new TransferTable();
String tableName = "book";
String transferTableName = "transformedBook";
// **************** 此处省略部分测试实现代码 ****************
// 获取到bookStore数据库的连接,调用transferTable函数进行数据表转换
Connection connection = transferTable.getConnection(transferTable.JDBC_DRIVER, transferTable.DB_URL, transferTable.USER, transferTable.PASS);
transferTable.transferTable(connection, tableName);
//**********此处省略结果检测的实现代码************
}
}
预期输出:
1004 title 平凡的世界
1004 publisher 人民文学出版社
1208 author 钱钟书
头歌实验代码
package step7;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.spi.DirStateFactory.Result;
public class TransferTable {
// 设定JDBC驱动以及本地数据库的URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql:///bookstore?useUnicode=true&characterEncoding=utf-8&useSSL=false";
// 指定数据库的用户名和密码
static final String USER = "root";
static final String PASS = "123123";
public void transferTable(Connection connection, String tableName) throws SQLException{
//请在此将转换表结构的函数补充完整。
ResultSet result = null;
Statement stmt = null;
String sqlScript = "select * from " + tableName + " order by id desc";
try {
stmt = connection.createStatement();
result = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
String sqlInsert = "insert into transformedBook (id,column_name,value) values (";
while (result.next()) {
String sql = "";
String id = result.getString("id");
String title=result.getString("title");
if(title != null)
{
sql = sqlInsert + id + ",'" + "title" + "','" + title + "');";
InsertRecord(connection, sql);
}
String author = result.getString("author");
if(author != null)
{
sql = sqlInsert + id + ",'" + "author" + "','" + author + "');";
InsertRecord(connection, sql);
}
String publisher = result.getString("publisher");
if(publisher != null)
{
sql = sqlInsert + id + ",'" + "publisher" + "','" + publisher + "');";
InsertRecord(connection, sql);
}
String publishYear = result.getString("publishYear");
if(publishYear != null)
{
sql = sqlInsert + id + ",'" + "publishYear" + "','" + publishYear + "');";
InsertRecord(connection, sql);
}
}
}
//插入数据
public void InsertRecord(Connection connection,String sqlScript){
Statement stmt = null;
try {
stmt = connection.createStatement();
stmt.executeUpdate(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
}
//查询数据库
public ResultSet queryDB(Connection connection, String tableName){
Statement stmt = null;
ResultSet result = null;
String sqlScript = "select * from " + tableName;
try {
stmt = connection.createStatement();
result = stmt.executeQuery(sqlScript);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
// 建立与指定数据库的连接,并返回该连接
public Connection getConnection(String jdbc_driver, String db_url, String db_user, String db_passwd) {
Connection connection = null;
//注册JDBC驱动
try {
Class.forName(jdbc_driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//创建于指定数据库的连接
try {
connection = (Connection) DriverManager.getConnection(db_url, db_user, db_passwd);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
}