3.2 在Java工程中使用MySQL的方法
下载Java连接MySQL所需要的驱动包mysql-connector-java-8.0.19.jar文件,并将其导入Java工程。
3.3 连接、断开MySQL服务器
在程序中加入” import java.sql.*;”。在程序连接数据之前需要:
1)加载驱动程序:
Class.forName(JDBC_DRIVER);
2)MySQL 8.0以上版本不需要建立SSL连接的,需要显式关闭,此外需要设置时间标准(UTC、GMT、CST)。在数据库的URL中设置以上内容:
String DB_URL =
"jdbc:mysql://localhost:3306/menagerie?useSSL=false&serverTimezone=UTC";
上面的数据库URL中指定了要使用的数据库“menagerie”。
3)通过调用DriverManager类的getConnection方法连接数据库,方式如下:
Connection con = DriverManager.getConnection(DB_URL,UID,PWD);
其中Connection类来自java.sql包;DB_URL为数据库URL,UID为数据库用户ID,PWD为登陆密码。
4)断开连接,方式如下:
conn.close();
3.4 查询MySQL数据库和提取查询结果
在成功连接MySQL 服务器后,可以使用Statement类的一个实例通过建立好的连接向数据库发送SQL语句,为此需要在连接变量con上建立一个Statement句柄(stmt):
Statement stmt = conn.createStatement();
随后,可以使用函数executeQuery和executeUpdate来执行查询或更新语句。下面的例子将执行一个查询:
String sql;
sql = "SELECT * FROM pet";
ResultSet rs = stmt.executeQuery(sql);
查询执行之后,从ResultSet中提取查询结果:
while(rs.next()){
String name = rs.getString("name");
String owner = rs.getString("owner");
String species = rs.getString("species");
Date birth = rs.getDate("birth");
Date death = rs.getDate(6);
}
结束所有查询和更新之后需要关闭ResultSet和Statement:
rs.close();
stmt.close();
下面是一个完整的例子:
import java.sql.*;
public class test {
// jdbc driver and db url
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/menagerie?useSSL=false&serverTimezone=UTC";
// user id and password
static final String USER = "root";
static final String PASS = "19830729";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Connection conn = null;
Statement stmt = null;
try{
// register your jdbc driver
Class.forName(JDBC_DRIVER);
// build a connection to database
System.out.println("connecting database ...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
// run a query
System.out.println("initiating a statement ...");
stmt = conn.createStatement();
String sql;
sql = "SELECT * FROM pet";
ResultSet rs = stmt.executeQuery(sql);
// iterate query results
while(rs.next()){
// extract values of different attributes by column names (results can be obtained using integer id)
String name = rs.getString("name");
String owner = rs.getString("owner");
String species = rs.getString("species");
Date birth = rs.getDate("birth");
Date death = rs.getDate(6);
// print results
System.out.print("name: " + name);
System.out.print(", owner: " + owner);
System.out.print(", species: " + species);
System.out.print(", birth: " + birth);
System.out.print(", death: " + death);
System.out.print("\n");
}
// close resources
rs.close();
stmt.close();
conn.close();
}catch(SQLException se){
// catch jdbc exceptions
se.printStackTrace();
}catch(Exception e){
// catch Class.forName errors
e.printStackTrace();
}
}
}
参考资料
Abraham Silberschatz, Henry F.Korth,《数据库系统概念(第六版)》p89-93.
上面的范例使用的素材是经典的Pet表格,表格内容如下:
数据库:menagerie,表格pet,表格内容:
首先是建立以下数据库与表格
数据库:company,表格:department,employee,works_on,project
Table department:
Table employee:
Table works_on:
Table project:
在上次上机实验课建立的COMPANY数据库上,用Java语言编写程序,完成如下查询,程序的命令行参数为:
company_query –q
-p [Parameters] 其中,Number代表待执行查询的序号,Parameters为第Number号查询需要的参数列表。
待执行的9个查询为如下:
1:参加了项目编号为%PNO%的项目的员工号,其中%PNO%为Java语言编写的程序的输入参数;
2:参加了项目名为%PNAME%的员工名字,其中%PNAME%为Java语言编写的程序的输入参数;
3:在%DNAME%工作的所有工作人员的名字和地址,其中%DNAME%为Java语言编写的程序的输入参数;
4:在%DNAME%工作且工资低于%SALARY%元的员工名字和地址,其中%DNAME%和%SALARY%为Java语言编写的程序的输入参数;
5:没有参加项目编号为%PNO%的项目的员工姓名,其中%PNO%为Java语言编写的程序的输入参数;
6:由%ENAME%领导的工作人员的姓名和所在部门的名字,其中%ENAME%为Java语言编写的程序的输入参数;
7:至少参加了项目编号为%PNO1%和%PNO2%的项目的员工号,其中%PNO1%和%PNO2%为Java语言编写的程序的输入参数;
8:员工平均工资低于%SALARY%元的部门名称,其中%SALARY%为Java语言编写的程序的输入参数;
9:至少参与了%N%个项目且工作总时间不超过%HOURS%小时的员工名字,其中%N%和%SALARY%为Java语言编写的程序的输入参数;
1、建立MySQL数据库连接,使用company数据库:
// jdbc驱动和数据库的url
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/company?useSSL=false&serverTimezone=UTC";
// 用户名和登录密码
static final String USER = "root";
static final String PASS = "20020712lcL";
// 注册jdbc驱动
Class.forName(JDBC_DRIVER);
// 和数据库建立连接
System.out.println("connecting database ...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
值得一提的是数据库url中,localhost:3306指代的是数据库使用端口为3306,这也是MySQL使用的端口号。后面的 “company” 就是本次所要使用的数据库。
2、提交数据库查询语句,这里以第一个查询为例子
// 提交查询语句
System.out.println("initiating a statement ...");
stmt = conn.createStatement();
String newcommand; // 接收键盘输入的命令
String sql; // 向数据库发出请求的语句
System.out.print(">>>"); // 输入提示符
Scanner scan = new Scanner(System.in);
newcommand = scan.nextLine();
String sql_PNO = newcommand.substring(22, newcommand.length()); // 获取命令-p后的参数
sql = "SELECT ESSN FROM works_on WHERE PNO=\"" + sql_PNO + "\";"; // 向数据库请求的具体语句(MySQL语言)
stmt.executeQuery(sql); // 向数据库提交语句
3、解析提交语句后产生的结果
ResultSet rs1 = stmt.executeQuery(sql); // 获取语句执行后返回的结果
while(rs1.next()) { // 获取查询结果并打印
String ESSN = rs1.getString("ESSN"); // 获取查询结果的属性对应的值
System.out.println("ESSN: " + ESSN); // 打印结果
}
4、关闭数据库连接
rs1.close(); // 获取结果关闭
stmt.close(); // 查询语句入口关闭
conn.close(); // 连接关闭
1、九条命令与quit命令演示:
2、程序健壮性与exit命令演示:
import java.sql.*;
import java.util.Scanner;
public class test {
// jdbc driver and db url
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/company?useSSL=false&serverTimezone=UTC";
// user id and password
static final String USER = "root";
static final String PASS = "20020712lcL";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Connection conn = null;
Statement stmt = null;
try{
// register your jdbc driver
Class.forName(JDBC_DRIVER);
// build a connection to database
System.out.println("connecting database ...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
// run a query
System.out.println("initiating a statement ...");
stmt = conn.createStatement();
String newcommand; //接收键盘输入的命令
String command_ini; //判别命令的前半部分是否符合标准
String command_para; //判断命令的中间部分是否符合标准
String sql; //向数据库发出请求的语句
while(true) { //支持多次输入命令
System.out.print(">>>"); //输入提示符
Scanner scan = new Scanner(System.in);
newcommand = scan.nextLine();
if (newcommand.equals("exit") || newcommand.equals("quit")) { //退出命令设置
// rs.close();
stmt.close();
conn.close();
System.out.println("程序已关闭!");
System.exit(0);
}
if (newcommand.length()<22) { //命令长短判断,防止之后截取时越界
System.out.println("无效的命令!");
continue;
}
command_ini = newcommand.substring(0, 17); //分别截取命令前半部分和中间部分
command_para = newcommand.substring(18, 22);
if (command_ini.equals("company_query -q ") &&
command_para.equals(" -p ")) { //判断命令是否符合标准
int command_num = Integer.parseInt(newcommand.substring(17, 18)); //获取命令种类(1~9)
switch(command_num) { //命令switch分类
case 1:
String sql_PNO = newcommand.substring(22, newcommand.length()); //获取-p后的参数
sql = "SELECT ESSN FROM works_on WHERE PNO=\"" + sql_PNO + "\";"; //向数据库请求的具体语句(MySQL语言)
//System.out.println(sql); //可打印语句,检查是否出现问题
ResultSet rs1 = stmt.executeQuery(sql);
while(rs1.next()) { //获取查询结果并打印
String ESSN = rs1.getString("ESSN");
System.out.println("ESSN: " + ESSN);
}
rs1.close();
break;
case 2:
String sql_PNAME = newcommand.substring(22, newcommand.length());
sql = "SELECT ENAME FROM works_on NATURAL JOIN "
+ "employee WHERE PNO= (select PNO from project "
+ "where PNAME=\"" + sql_PNAME + "\");";
//System.out.println(sql);
ResultSet rs2 = stmt.executeQuery(sql);
while(rs2.next()) {
String ENAME = rs2.getString("ENAME");
System.out.println("ENAME: " + ENAME);
}
rs2.close();
break;
case 3:
String sql_DNAME = newcommand.substring(22, newcommand.length());
sql = "SELECT ENAME, ADDRESS FROM EMPLOYEE "
+ "WHERE DNO= (select DNO from department "
+ "where DNAME=\"" + sql_DNAME + "\");";
//System.out.println(sql);
ResultSet rs3 = stmt.executeQuery(sql);
while(rs3.next()) {
String ENAME = rs3.getString("ENAME");
String ADDRESS = rs3.getString("ADDRESS");
System.out.println("ENAME: " + ENAME);
System.out.println("ADDRESS: " + ADDRESS);
}
rs3.close();
break;
case 4:
String sql_4_DNAME = newcommand.substring(22, newcommand.indexOf(','));
String sql_4_SALARY = newcommand.substring(newcommand.indexOf(',')+1,
newcommand.length());
sql = "SELECT ENAME, ADDRESS FROM EMPLOYEE "
+ "WHERE SALARY<"+sql_4_SALARY+" AND DNO= (select DNO from department "
+ "where DNAME=\"" + sql_4_DNAME + "\");";
//System.out.println(sql);
ResultSet rs4 = stmt.executeQuery(sql);
while(rs4.next()) {
String ENAME = rs4.getString("ENAME");
String ADDRESS = rs4.getString("ADDRESS");
System.out.println("ENAME: " + ENAME);
System.out.println("ADDRESS: " + ADDRESS);
}
rs4.close();
break;
case 5:
String sql_5_PNO = newcommand.substring(22, newcommand.length());
sql = "SELECT ENAME FROM EMPLOYEE "
+ "WHERE ESSN NOT IN (select ESSN from works_on "
+ "where PNO=\"" + sql_5_PNO + "\");";
//System.out.println(sql);
ResultSet rs5 = stmt.executeQuery(sql);
while(rs5.next()) {
String ENAME = rs5.getString("ENAME");
System.out.println("ENAME: " + ENAME);
}
rs5.close();
break;
case 6:
String sql_6_ENAME = newcommand.substring(22, newcommand.length());
sql = "SELECT ENAME,DNAME FROM EMPLOYEE NATURAL JOIN DEPARTMENT "
+ "WHERE SUPERSSN=(SELECT ESSN FROM EMPLOYEE "
+ "where ENAME=\"" + sql_6_ENAME + "\");";
//System.out.println(sql);
ResultSet rs6 = stmt.executeQuery(sql);
while(rs6.next()) {
String ENAME = rs6.getString("ENAME");
String DNAME = rs6.getString("DNAME");
System.out.println("ENAME: " + ENAME);
System.out.println("DNAME: " + DNAME);
}
rs6.close();
break;
case 7:
String sql_7_PNO1 = newcommand.substring(22, newcommand.indexOf(','));
String sql_7_PNO2 = newcommand.substring(newcommand.indexOf(',')+1,
newcommand.length());
sql = "SELECT ESSN FROM works_on "
+ "WHERE PNO=\""+sql_7_PNO1+"\" AND ESSN IN "
+ "(SELECT ESSN FROM works_on "
+ "where PNO=\"" + sql_7_PNO2 + "\");";
//System.out.println(sql);
ResultSet rs7 = stmt.executeQuery(sql);
while(rs7.next()) {
String ESSN = rs7.getString("ESSN");
System.out.println("ESSN: " + ESSN);
}
rs7.close();
break;
case 8:
String sql_8_SALARY = newcommand.substring(22, newcommand.length());
sql = "SELECT DNAME FROM DEPARTMENT "
+ "WHERE DNO IN (select DNO from EMPLOYEE GROUP BY DNO "
+ "HAVING AVG(SALARY)<" + sql_8_SALARY + ");";
//System.out.println(sql);
ResultSet rs8 = stmt.executeQuery(sql);
while(rs8.next()) {
String DNAME = rs8.getString("DNAME");
System.out.println("DNAME: " + DNAME);
}
rs8.close();
break;
case 9:
String sql_9_N = newcommand.substring(22, newcommand.indexOf(','));
String sql_9_HOURS = newcommand.substring(newcommand.indexOf(',')+1,
newcommand.length());
sql = "SELECT ENAME FROM EMPLOYEE NATURAL JOIN WORKS_ON "
+ "WHERE ESSN IN (SELECT ESSN FROM WORKS_ON "
+ "GROUP BY ESSN HAVING SUM(HOURS)<"+sql_9_HOURS
+ ")GROUP BY ESSN HAVING COUNT(PNO)>=" + sql_9_N + ";";
//System.out.println(sql);
ResultSet rs9 = stmt.executeQuery(sql);
while(rs9.next()) {
String ENAME = rs9.getString("ENAME");
System.out.println("ENAME: " + ENAME);
}
rs9.close();
break;
default:
System.out.println("无效的命令!");
continue;
}//switch end
}//if end
else {
System.out.println("无效的命令!");
continue;
}//else end
}//while end
}catch(SQLException se){
// catch jdbc exceptions
se.printStackTrace();
}catch(Exception e){
// catch Class.forName errors
e.printStackTrace();
}
}
}
注意:在用Java等高级语言访问数据库之前需要启动数据库服务,即通过cmd运行net start mysql语句。