HNU编程新技术实务实验一
实验描述
实验目的
安装、配置好Java编程环境、数据库环境,使用Java 进行编程以及数据库编程。
实验对应知识点
Java编译、运行,path、classpath环境变量,规范注释。数据库的JDBC驱动。
实验前任务
学习Java的基本语法以及数据库的理论基础。
实验要求及步骤
1.Java环境的安装、配置
2.安装开发工具Eclipse IDE for JavaEE或者MyEclipse
3.数据库的安装配置
实验内容
数据库编程
在安装配置好Mysql数据库后,使用Java语言通过JDBC直接连接数据库,在数据库中建表并进行表数据的增删查改。
关键代码:
……
Class.forName(……); //加载数据库驱动名
String url=……; //数据连接的url
String name=……; //数据库访问的用户名
String password=……; //数据库访问的密码
Connection con= DriverManager.getConnection(url, name, password);
……
在安装配置好数据库Mysql后,需要使用Java编程完成如下任务:
(1)创建数据库表users,字段分别为username(主键,varchar(10))、pass(varchar(8));数据库表person,字段按分别为username(varchar(10),对应于users表的username)、name(主键,varchar(20))、age(int,可以为空)、teleno(char(11),可以为空);如表users中username则表person中也不能有相应的username的数据。
(2)在表users中插入4行数据,数据分别是(ly,123456)、(liming,345678)、(test, 11111)、(test1,12345),在表person中插入3行数据,数据分别为(ly,雷力)、(liming,李明,25)、(test,测试用户,20,13388449933);
(3)在person表中插入5行数据,分别为(ly,王五)、(test2,测试用户2)、(test1,测试用户1,33)、(test,张三,23,18877009966)、(admin,admin)。对于表中已有的username,则根据最新的数据修改其相应字段值;如该username不存在,则首先在表users中插入该username,默认的password为888888,然后才能将数据插入至person表。
(4)删除users表中test打头的username,同时按照规则一并删除person表相应的数据。
要求每个处理阶段均要在控制台打印出处理完成后的结果,格式按照制表方式输出,如:
表users
字段名xx 字段名xx ….
xx xx
表person
字段名xx 字段名xx ….
xx xx
(5)类的设计要求:需要将数据库的连接、操作进行封装,以便在后续实验中进行重用。此项为扣分项,没有进行封装的实验分会相应扣减。
自此实验结束,按照要求提交源代码进行验收。
提示:以下是本篇文章正文内容,下面案例可供参考
实验步骤
一、准备步骤
1.下载安装navicat数据库可视化工具
安装后连接自己安装的sql数据库
2.下载并导入jar包
下载和自己数据库版本相匹配的jar驱动包,这里需要注意版本号一定要匹配,例如如果数据库版本是5.*而jar包的版本是8.*就会报错
3.在eclipse中新建工程
打开eclipse,选择workplace。
左上角 File -> New -> Java Project
单击Finish即可创建
在工程下面新建package
单击Finish即可
新建一个java类
最后把下载的jar包放到项目中:
项目名右键-> Build Path ->Configure Build Path
按图所示添加jar到项目,选择自己的jar路径添加即可
二、代码详情
代码结构分析
我的代码结构如下(示例):
其中:
Add,Delete,Query,Update,Print+Database 分别代表的封装数据库的增删查改和打印的操作
CreateDatabase 封装了创建数据库表
MysqlManager封装了连接数据库、断开数据库的操作
代码如下(示例):
Main.java
主函数类。
定义person和user类、包含创建person和user表的sql语句,针对于四个问题一一解答
package test1;
import java.sql.Connection;
public class Main {
public static Connection mConnect;
public static class Person {
String username;
String name;
int age = -1;
String teleno;
String SQLAdd;
}
public static class Users {
String username;
String pass;
}
public static String createperson = "CREATE TABLE person(" + "username varchar(10) not null,"
+ "name varchar(20) not null primary key," + "age int(4)," + "teleno char(11)" + ")charset=gbk;";
public static String createusers = "CREATE TABLE users(" + "username varchar(10) primary key,"
+ "pass varchar(20) not null" + ")charset=gbk;";
// public static String personAddTemplate = "insert into '%s'
// values('%s','%s','%d','%s')";
// public static String usersAddTemplate = "insert into users(username,name)
// values(%s,%s)";
public static void main(String[] args) {
// 获取全局操作connection 实例
MysqlManager mConnectManager = new MysqlManager();
mConnect = mConnectManager.getConnection();
// test111 test111 = new test111();
// System.out.println(test1.test111.test222());
// 获取添加操作实例
CreateDatabase db = new CreateDatabase(mConnect);
// test111.test222();
// 新建表
question1(db);
// 添加数据
AddDatabase add = new AddDatabase(mConnect);
question2(add);
// 添加、修改数据
UpdateDatabase update = new UpdateDatabase(mConnect);
question3(add, update);
// 删除数据
DeleteDatabase delete = new DeleteDatabase(mConnect);
question4(delete);
// 关闭连接
mConnectManager.close();
}
public static void question1(CreateDatabase db) {
db.createTable(createperson);
db.createTable(createusers);
System.out.println("\nQuestion 1:");
PrintDatabase.printTable(mConnect);
}
public static void question2(AddDatabase Add) {
Person[] person = new Person[3];
Users[] users = new Users[4];
for (int i = 0; i < person.length; i++) {
person[i] = new Person();
}
for (int i = 0; i < users.length; i++) {
users[i] = new Users();
}
person[0].username = "ly";
person[0].name = "雷力";
person[1].username = "liming";
person[1].name = "李明";
person[1].age = 25;
person[2].username = "test";
person[2].name = "测试用户";
person[2].age = 20;
person[2].teleno = "13388449933";
users[0].username = "ly";
users[0].pass = "123456";
users[1].username = "liming";
users[1].pass = "345678";
users[2].username = "test";
users[2].pass = "11111";
users[3].username = "test1";
users[3].pass = "12345";
for (int i = 0; i < person.length; i++) {
Add.addData("person", person[i]);
}
for (int i = 0; i < users.length; i++) {
Add.addData("users", users[i]);
}
// Add.add("person", person[0].username, person[0].name);
// Add.add("person", person[1].username, person[1].name, person[1].age);
// Add.add("person", person[2].username, person[2].name, person[2].age, person[2].teleno);
System.out.println("\nQuestion 2:");
PrintDatabase.printTable(mConnect);
}
public static void question3(AddDatabase Add, UpdateDatabase Update) {
Person[] person = new Person[5];
boolean[] boolflag = new boolean[5];
for (int i = 0; i < person.length; i++) {
person[i] = new Person();
boolflag[i] = false;
}
person[0].username = "ly";
person[0].name = "王五";
person[1].username = "test2";
person[1].name = "测试用户2";
person[1].age = 2;
person[2].username = "test1";
person[2].name = "测试用户1";
person[2].age = 33;
person[3].username = "test";
person[3].name = "张三";
person[3].age = 23;
person[3].teleno = "18877009966";
person[4].username = "admin";
person[4].name = "admin";
for (int i = 0; i < person.length; i++) {
if (QueryDatabase.query(mConnect, person[i].username) == false) {
// 表中没有,在users中插入username,pass = 888888
// System.out.printf("111 %s\n", person[i].username);
// 新建对象
Users user = new Users();
// 赋值
user.username = person[i].username;
user.pass = "888888";
// 添加数据
// ERROR : 这里的test1在users 表中已有,会插入失败
Add.addData("users", user);
Add.addData("person", person[i]);
} else {
// 表中有,更新数据
// System.out.printf("222 %s\n", person[i].username);
Update.updateData("person", person[i]);
}
}
System.out.println("\nQuestion 3:");
PrintDatabase.printTable(mConnect);
// Add.add("person", person[0].username, person[0].name);
// Add.add("person", person[1].username, person[1].name, person[1].age);
// Add.add("person", person[2].username, person[2].name, person[2].age, person[2].teleno);
}
public static void question4(DeleteDatabase Delete) {
Delete.deleteData("person", "test");
Delete.deleteData("users", "test");
System.out.println("\nQuestion 4:");
PrintDatabase.printTable(mConnect);
}
}
MysqlManager.java
管理连接类。
其中的配置来自于配置文件,当然也可以自己写,但是写到配置文件里方便修改,并且可以加分。
需要 import java.util.Properties;
package test1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class MysqlManager {
private Connection mConnect;
public MysqlManager() {
Properties props = new Properties();
try {
props.load(new FileInputStream("config.properties"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
// 通过String getProperty(String key)来获取配置文件中key对应的value
String mysqlDriver = props.getProperty("mysqlDriver");
String mysqlUrl = props.getProperty("mysqlUrl");
String username = props.getProperty("mysqlUsername");
String password = props.getProperty("mysqlPassword");
try {
// 注册驱动
Class.forName(mysqlDriver);
// 创建一个链接对象
mConnect = DriverManager.getConnection(mysqlUrl, username, password);
System.out.println("Connect successfully! ");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
// 返回connection 实例
public Connection getConnection() {
return mConnect;
}
// 关闭连接
public void close() {
try {
mConnect.close();
System.out.println("Close successfully! ");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
配置文件如下:
mysqlDriver=com.mysql.jdbc.Driver
mysqlUrl=jdbc:mysql://localhost:3306/test
mysqlUsername=root
mysqlPassword=123456
放在图示位置,可以在文件夹下新建一个txt问文件,然后修改文件的后缀名如图即可。如何修改后缀名?
CreateDatabase.java
创建表的类。
构造函数为获取connection实例;createTable函数接受一个创建表的sql语句作为参数,其已在main函数中写好。
package test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class CreateDatabase {
public Connection mConnect;
public CreateDatabase(Connection connection) {
this.mConnect = connection;
}
public void createTable(String sql) {
PreparedStatement createStatement = null;
try {
createStatement = mConnect.prepareStatement(sql);
createStatement.execute();
System.out.println("create database successfully!");
} catch (SQLException e) {
System.out.println("创建表异常:" + e.getMessage());
} finally {
try {
createStatement.close();
} catch (SQLException e) {
System.out.println("关闭表异常:" + e.getMessage());
}
}
}
}
AddDatabase.java
增加类。
因为传入参数数量的不确定(例如添加person的时候不知道有没有age和teleno)我使用了重载add函数来解决这一问题(使用变长参数也可以解决)。
其中构造函数接受传入的connection实例;函数的作用和返回值如注释
package test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import test1.Main.Person;
import test1.Main.Users;
public class AddDatabase {
public Connection mConnect;
public AddDatabase(Connection connection) {
this.mConnect = connection;
}
/*
* addData方法: 接收来自主函数的调用 重载两种参数:person 和 user
*
*/
public void addData(String table, Person person) {
if (person.age == -1 && person.teleno == null) {
// 都没有
add(table, person.username, person.name);
} else if (person.age != -1 && person.teleno == null) {
// 有age
add(table, person.username, person.name, person.age);
} else {
add(table, person.username, person.name, person.age, person.teleno);
}
}
public void addData(String table, Users user) {
add(table, user.username, user.pass);
}
/*
* add方法: 接受来自addData的调用 重载接收三种变长参数 返回值:是否添加成功
*
*/
private boolean add(String table, String username, String name) {
if (table == "person") {
String sql = "insert into person(username,name) values('%s','%s')";
sql = String.format(sql, username, name);
return executeAddSQL(table, sql);
} else {
String sql = "insert into users(username,pass) values('%s','%s')";
sql = String.format(sql, username, name);
return executeAddSQL(table, sql);
}
}
private boolean add(String table, String username, String name, int age) {
String sql = "insert into person(username,name,age) values('%s','%s','%d')";
sql = String.format(sql, username, name, age);
return executeAddSQL(table, sql);
}
private boolean add(String table, String username, String name, int age, String teleno) {
String sql = "insert into person(username,name,age,teleno) values('%s','%s','%d','%s')";
sql = String.format(sql, username, name, age, teleno);
return executeAddSQL(table, sql);
}
/*
* 执行函数,执行executeUpdate方法 返回值:执行是否成功
*/
private boolean executeAddSQL(String table, String sqlString) {
PreparedStatement addStatement = null;
try {
addStatement = mConnect.prepareStatement(sqlString); // 创建statement类对象,用来执行SQL语句!!
addStatement.executeUpdate();
System.out.println(String.format("Insert %s seccessfully! ", table));
return true;
} catch (SQLException e) {
System.out.println("添加表异常:" + e.getMessage());
return false;
} finally {
try {
addStatement.close();
} catch (SQLException e) {
System.out.println("关闭prepareStatement异常:" + e.getMessage());
}
}
}
}
DeleteDatabase.java
删除类。
我写的逻辑是先依据username查询需要删除的name,把这些name放到一个list中,然后去数据库中做删除操作
package test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
/*
* 可以删除person或者users表,以username作为查找值
*/
public class DeleteDatabase {
public Connection mConnect;
public DeleteDatabase(Connection connection) {
this.mConnect = connection;
}
public void deleteData(String table, String deleteIndex) {
// 先查询,然后删除
String sqlQuery = String.format("SELECT * FROM %s WHERE username LIKE '%s%s'", table, deleteIndex, "%");
String sqlDetele = String.format("DELETE FROM %s WHERE username = ?", table);
ArrayList<String> deleteNameArrayString = new ArrayList<>();
PreparedStatement queryStatement = null;
ResultSet queryResult = null;
try {
queryStatement = mConnect.prepareStatement(sqlQuery);
// queryStatement.setString(1, table);
queryResult = queryStatement.executeQuery();
while (queryResult.next()) {
// if (queryResult.getString("username").trim().toString().contains("test")) {
// deleteNameArrayString.add(queryResult.getString("username").trim().toString());
// }
deleteNameArrayString.add(queryResult.getString("username"));
}
} catch (SQLException e) {
System.out.println("查询表异常:" + e.getMessage() + "在deleteDatabase中");
} finally {
try {
queryStatement.close();
} catch (SQLException e) {
System.out.println("关闭PreparedStatement异常:" + e.getMessage());
}
try {
queryResult.close();
} catch (SQLException e) {
System.out.println("关闭ResultSet异常:" + e.getMessage());
}
}
for (int i = 0; i < deleteNameArrayString.size(); i++) {
PreparedStatement deleteStatement = null;
try {
deleteStatement = mConnect.prepareStatement(sqlDetele);
// deleteStatement.setString(1, table);
deleteStatement.setString(1, deleteNameArrayString.get(i));
deleteStatement.executeUpdate();
System.out.println("Delete Successfully! ");
} catch (SQLException e) {
System.out.println("删除表异常:" + e.getMessage());
} finally {
try {
deleteStatement.close();
} catch (SQLException e) {
System.out.println("关闭PreparedStatement异常:" + e.getMessage());
}
}
}
}
}
QueryDatabase.java
查询类。
以username作为查询值在person表中查询是否存在
package test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class QueryDatabase {
public static String sql = "SELECT * FROM person where username=?";
/*
* 给定username查询数据库是否存在 返回bool
*/
public static boolean query(Connection mConnect, String username) {
PreparedStatement queryStatement = null;
ResultSet result = null;
boolean status = false;
try {
queryStatement = mConnect.prepareStatement(sql);
queryStatement.setString(1, username);
// statement = mConnect.createStatement(); // 创建statement类对象,用来执行SQL语句!!
result = queryStatement.executeQuery();
while (result.next()) {
// System.out.println((result.getString("username").trim().toString().equals(username)));
if (result.getString("username").trim().toString().equals(username)) {
status = true;
}
}
} catch (SQLException e) {
System.out.println("查询表异常:" + e.getMessage());
status = false;
} finally {
try {
queryStatement.close();
} catch (SQLException e) {
System.out.println("关闭PreparedStatement异常:" + e.getMessage());
}
try {
result.close();
} catch (SQLException e) {
System.out.println("关闭ResultSet异常:" + e.getMessage());
}
}
return status;
}
}
UpdateDatabase.java
修改类。
类似于增加类,因为不能确定一次修改几个值,所以我使用了重载来解决问题。
与增加类不同的是我把关闭操作封装成了一个函数,其实增加类也应该这么干,但是已经写完了就懒得改了。。
(有关这个关闭的问题其实还挺大的,这样写也不合适,最后会讲)
package test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import test1.Main.Person;
import test1.Main.Users;
public class UpdateDatabase {
private Connection mConnect;
public UpdateDatabase(Connection connection) {
this.mConnect = connection;
}
/*
* 可以修改person或者users表,以username作为查找值
*/
public void updateData(String table, Person person) {
if (person.age == -1 && person.teleno == null) {
// 都没有
update(table, person.username, person.name);
} else if (person.age != -1 && person.teleno == null) {
// 有age
update(table, person.username, person.name, person.age);
} else {
update(table, person.username, person.name, person.age, person.teleno);
}
}
public void updateData(String table, Users user) {
update(table, user.username, user.pass);
}
private void update(String table, String username, String name) {
if (table == "person") {
PreparedStatement updateStatement = null;
String sql = "UPDATE person SET name = ? WHERE username = ?";
try {
updateStatement = mConnect.prepareStatement(sql); // 创建statement类对象,用来执行SQL语句!!
updateStatement.setString(1, name);
updateStatement.setString(2, username);
updateStatement.executeUpdate();
System.out.println("Update person seccessfully! ");
} catch (SQLException e) {
System.out.println("更新表异常:" + e.getMessage());
} finally {
closePreparedStatement(updateStatement);
}
} else {
PreparedStatement updateStatement = null;
String sql = "UPDATE users SET pass = ? WHERE username = ?";
try {
updateStatement = mConnect.prepareStatement(sql); // 创建statement类对象,用来执行SQL语句!!
updateStatement.setString(1, name);
updateStatement.setString(2, username);
updateStatement.executeUpdate();
System.out.println("Update person seccessfully! ");
} catch (SQLException e) {
System.out.println("更新表异常:" + e.getMessage());
} finally {
closePreparedStatement(updateStatement);
}
}
}
private void update(String table, String username, String name, int age) {
PreparedStatement updateStatement = null;
String sql = "UPDATE person SET name = ?,age = ? WHERE username = ?";
try {
updateStatement = mConnect.prepareStatement(sql); // 创建statement类对象,用来执行SQL语句!!
updateStatement.setString(1, name);
updateStatement.setInt(2, age);
updateStatement.setString(3, username);
updateStatement.executeUpdate();
System.out.println("Update person seccessfully! ");
} catch (SQLException e) {
System.out.println("更新表异常:" + e.getMessage());
} finally {
closePreparedStatement(updateStatement);
}
}
private void update(String table, String username, String name, int age, String teleno) {
PreparedStatement updateStatement = null;
String sql = "UPDATE person SET name = ?,age = ?,teleno = ? WHERE username = ?";
try {
updateStatement = mConnect.prepareStatement(sql); // 创建statement类对象,用来执行SQL语句!!
updateStatement.setString(1, name);
updateStatement.setInt(2, age);
updateStatement.setString(3, teleno);
updateStatement.setString(4, username);
updateStatement.executeUpdate();
System.out.println("Update person seccessfully! ");
} catch (SQLException e) {
System.out.println("更新表异常:" + e.getMessage());
} finally {
closePreparedStatement(updateStatement);
}
}
private void closePreparedStatement(PreparedStatement updateStatement) {
try {
updateStatement.close();
} catch (SQLException e) {
System.out.println("关闭PreparedStatement异常:" + e.getMessage());
}
}
}
PrintDatabase.java
打印类。
查询并打印user表和person表的数据
package test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class PrintDatabase {
public static void printTable(Connection mConnect) {
System.out.println("\nTable person");
String sqlPerson = "SELECT * FROM person";
PreparedStatement printStatementPerson = null;
ResultSet resultPerson = null;
try {
printStatementPerson = mConnect.prepareStatement(sqlPerson); // 创建statement类对象,用来执行SQL语句!!
resultPerson = printStatementPerson.executeQuery();
System.out.println("field username field name field age field teleno");
while (resultPerson.next()) {
if (resultPerson.getString("username") != null) {
System.out.printf("%s \t\t\t", resultPerson.getString("username"));
}
if (resultPerson.getString("name") != null) {
System.out.printf("%s \t\t\t", resultPerson.getString("name"), " ");
}
if (resultPerson.getString("age") != null) {
System.out.printf("%s \t\t\t", resultPerson.getString("age"), " ");
}
if (resultPerson.getString("teleno") != null) {
System.out.printf("%s \t\t\t", resultPerson.getString("teleno"), " ");
}
System.out.println();
}
} catch (SQLException e) {
System.out.println("输出表异常:" + e.getMessage());
} finally {
try {
printStatementPerson.close();
} catch (SQLException e) {
System.out.println("关闭prepareStatement异常:" + e.getMessage());
}
try {
resultPerson.close();
} catch (SQLException e) {
System.out.println("关闭ResultSet异常:" + e.getMessage());
}
}
System.out.println("\nTable users");
String sqlUsers = "SELECT * FROM users";
ResultSet resultUsers = null;
PreparedStatement printStatementUsers = null;
try {
printStatementUsers = mConnect.prepareStatement(sqlUsers); // 创建statement类对象,用来执行SQL语句!!
resultUsers = printStatementUsers.executeQuery();
System.out.println("field username field pass");
while (resultUsers.next()) {
if (resultUsers.getString("username") != null) {
System.out.printf("%s \t\t\t", resultUsers.getString("username"));
}
if (resultUsers.getString("pass") != null) {
System.out.printf("%s \t\t\t", resultUsers.getString("pass"), " ");
}
System.out.println();
}
System.out.println("\n");
} catch (SQLException e) {
System.out.println("输出表异常:" + e.getMessage());
} finally {
try {
printStatementUsers.close();
} catch (SQLException e) {
System.out.println("关闭prepareStatement异常:" + e.getMessage());
}
try {
resultUsers.close();
} catch (SQLException e) {
System.out.println("关闭ResultSet异常:" + e.getMessage());
}
}
}
}
三、一些问题
1.应该把preparedStatement 抽象成一个类,否则每次都要创建一个对象
2.封装的问题。有些类的设计专门为了这些实验题目,并没有真正意义上的实现对数据库的增删查改的封装。
在Main类中写的一系列函数只限于这次的实验题目
四、可能存在的错误
1.jar包的版本和安装的数据库版本不匹配,我用的数据库版本是5.0.37,jar包的版本是5.1.49
(终端命令登录 mysql –u root –p,登陆的日志里面有版本号)
2.数据库配置文件config.properties的用户名和密码没有修改成自己设置的
3.没有第三条了。。只写两条好像有点太少了:)
总结
以上代码仅供参考(在我电脑上跑的通),随着需求的变化可能会需要更改。
如有错误,敬请谅解。