实验4 NoSQL和关系数据库的操作比较
1. 实验目的
(1)理解四种数据库(MySQL、 HBase、 Redis 和 MongoDB)的概念以及不同点;
(2)熟练使用四种数据库操作常用的 Shell 命令;
(3)熟悉四种数据库操作常用的 Java API。
2.实验平台
(1) 操作系统: Linux(Ubuntu-22.04.2);
(2) Hadoop 版本: 3.1.3;
(3) MySQL 版本: 8.0.32;
(4) HBase 版本: 2.2.2;
(5) Redis 版本: 7.0.10;
(6) MongoDB 版本: 6.0.5;
(7) JDK 版本: 1.8;
(8) Java IDE: Eclipse;
3.实验步骤与结果
(一) MySQL 数据库操作
学生表如 14-7 所示。
表 14-7 学生表 Student
Name |
English |
Math |
Computer |
zhangsan |
69 |
86 |
77 |
lisi |
55 |
100 |
88 |
\1. 根据上面给出的 Student 表,在 MySQL 数据库中完成如下操作:
(1)在 MySQL 中创建 Student 表,并录入数据;
(2) 用 SQL 语句输出 Student 表中的所有记录;
(3) 查询 zhangsan 的 Computer 成绩;
(4) 修改 lisi 的 Math 成绩, 改为 95。
2.根据上面已经设计出的 Student 表,使用 MySQL 的 JAVA 客户端编程实现以下操作
(1)向 Student 表中添加如下所示的一条记录:
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import java.sql.*; public class mysql_test {
static final String DRIVER="com.mysql.cj.jdbc.Driver"; static final String DB="jdbc:mysql://localhost/mysql?useSSL=false"; static final String USER="root"; static final String PASSWD="mynewpassword";
public static void main(String[] args) { Connection conn=null; Statement stmt=null; try { Class.forName(DRIVER); System.out.println("Connecting to a selected database..."); conn=DriverManager.getConnection(DB, USER, PASSWD); stmt=conn.createStatement(); String sql="insert into student values('scofield',45,89,100)"; stmt.executeUpdate(sql); System.out.println("Inserting records into the table successfully!"); } catch (ClassNotFoundException e) { e.printStackTrace(); }catch (SQLException e) { e.printStackTrace(); }finally { if(stmt!=null) try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
|
(2) 获取 scofield 的 English 成绩信息
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import java.sql.*; public class mysql_qurty {
static final String DRIVER="com.mysql.cj.jdbc.Driver"; static final String DB="jdbc:mysql://localhost/mysql?useSSL=false"; static final String USER="root"; static final String PASSWD="mynewpassword";
public static void main(String[] args) { Connection conn=null; Statement stmt=null; ResultSet rs=null; try { Class.forName(DRIVER); System.out.println("Connecting to a selected database..."); conn=DriverManager.getConnection(DB, USER, PASSWD); stmt=conn.createStatement(); String sql="select name,English from student where name='scofield' "; rs=stmt.executeQuery(sql); System.out.println("name"+"\t\t"+"English"); while(rs.next()) { System.out.print(rs.getString(1)+"\t\t"); System.out.println(rs.getInt(2)); } } catch (ClassNotFoundException e) { e.printStackTrace(); }catch (SQLException e) { e.printStackTrace(); }finally { if(rs!=null) try { rs.close(); } catch (SQLException e1) { e1.printStackTrace(); } if(stmt!=null) try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
|
(二) HBase 数据库操作
学生表 Student 如表 14-8 所示。
表 14-8 学生表 Student
name |
score |
|
|
English |
Math |
Computer |
|
zhangsan |
69 |
86 |
77 |
lisi |
55 |
100 |
88 |
\1. 根据上面给出的学生表 Student 的信息, 执行如下操作:
(1) 用 Hbase Shell 命令创建学生表 Student;
(2)用 scan 命令浏览 Student 表的相关信息;
(3)查询 zhangsan 的 Computer 成绩;
(4)修改 lisi 的 Math 成绩, 改为 95。
2.根据上面已经设计出的 Student 表, 用 HBase API 编程实现以下操作:
(1)添加数据: English:45 Math:89 Computer:100
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Table;
public class hbase_insert {
public static Configuration configuration; public static Connection connection; public static Admin admin; public static void main(String[] args) { configuration = HBaseConfiguration.create(); configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase");
try{ connection = ConnectionFactory.createConnection(configuration); admin = connection.getAdmin(); }catch (IOException e){ e.printStackTrace(); } try { insertRow("student","scofield","score","English","45"); insertRow("student","scofield","score","Math","89"); insertRow("student","scofield","score","Computer","100"); } catch (IOException e) { e.printStackTrace(); } close(); } public static void insertRow(String tableName,String rowKey,String colFamily, String col,String val) throws IOException { Table table = connection.getTable(TableName.valueOf(tableName)); Put put = new Put(rowKey.getBytes()); put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes()); table.put(put); table.close(); } public static void close(){ try{ if(admin != null){ admin.close(); } if(null != connection){ connection.close(); } }catch (IOException e){ e.printStackTrace(); } } }
|
执行完上述代码以后,可以用scan命令输出数据库数据,以检验是否插入成功,执行结果截图如图所示。
(2) 获取 scofield 的 English 成绩信息。
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Table;
public class hbase_query {
public static Configuration configuration; public static Connection connection; public static Admin admin; public static void main(String[] args) { configuration = HBaseConfiguration.create(); configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase"); try{ connection = ConnectionFactory.createConnection(configuration); admin = connection.getAdmin(); }catch (IOException e){ e.printStackTrace(); } try { getData("student","scofield","score","English"); } catch (IOException e) { e.printStackTrace(); } close(); } public static void getData(String tableName,String rowKey,String colFamily, String col)throws IOException{ Table table = connection.getTable(TableName.valueOf(tableName)); Get get = new Get(rowKey.getBytes()); get.addColumn(colFamily.getBytes(),col.getBytes()); Result result = table.get(get); showCell(result); table.close(); } public static void showCell(Result result){ Cell[] cells = result.rawCells(); for(Cell cell:cells){ System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" "); System.out.println("Timetamp:"+cell.getTimestamp()+" "); System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" "); System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" "); System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" "); } } public static void close(){ try{ if(admin != null){ admin.close(); } if(null != connection){ connection.close(); } }catch (IOException e){ e.printStackTrace(); } } }
|
控制台中输出如下信息:
(三) Redis 数据库操作
Student 键值对如下:
zhangsan:{ English: 69 Math: 86 Computer: 77 } lisi:{ English: 55 Math: 100 Computer: 88 }
\1. 根据上面给出的键值对, 完成如下操作:
( 1) 用 Redis 的哈希结构设计出学生表 Student( 键值可以用 student.zhangsan 和
student.lisi 来表示两个键值属于同一个表);
(2) 用 hgetall 命令分别输出 zhangsan 和 lisi 的成绩信息;
(3) 用 hget 命令查询 zhangsan 的 Computer 成绩;
(4)修改 lisi 的 Math 成绩, 改为 95。
2.根据上面已经设计出的学生表 Student, 用 Redis 的 JAVA 客户端编程(jedis),实现如下操
作:
(1)添加数据: English:45 Math:89 Computer:100
该数据对应的键值对形式如下:
scofield:{ English: 45 Math: 89 Computer: 100 }
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import redis.clients.jedis.Jedis; public class jedis_test { public static void main(String[] args) { Jedis jedis = new Jedis("localhost"); System.out.println("连接成功");
String re = jedis.hget("Student.scofield", "English"); System.out.println(re); } }
|
(2) 获取 scofield 的 English 成绩信息
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import java.util.Map;
import redis.clients.jedis.Jedis;
public class jedis_query {
public static void main(String[] args) {
*
Jedis jedis = new Jedis("localhost");
String value=jedis.hget("student.scofield", "English");
System.out.println("scofield's English score is: "+value);
}
}
|
(四) MongoDB 数据库操作
Student 文档如下:
{ “name”: “zhangsan”, “score”: { “English”: 69, “Math”: 86, “Computer”: 77 } } { “name”: “lisi”, “score”: { “English”: 55, “Math”: 100, “Computer”: 88 } }
1.根据上面给出的文档,完成如下操作:
(1) 用 MongoDB Shell 设计出 student 集合;
(2) 用 find()方法输出两个学生的信息;
(3) 用 find()方法查询 zhangsan 的所有成绩(只显示 score 列);
(4)修改 lisi 的 Math 成绩, 改为 95。
2.根据上面已经设计出的 Student 集合,用 MongoDB 的 Java 客户端编程,实现如下操作:
(1) 添加数据: English:45 Math:89 Computer:100
与上述数据对应的文档形式如下:
{ “name”: “scofield”, “score”: { “English”: 45, “Math”: 89, “Computer”: 100 } }
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.bson.Document; import org.bson.conversions.Bson; import com.mongodb.*; import com.mongodb.client.*; import com.mongodb.client.model.Filters;
public class mongo_insert { MongoClient mongoClient; MongoDatabase mongoDatabase; public mongo_insert(String databasename) { this.getConnect(databasename); } public mongo_insert(String username,String password,String databasename) { this.getConnectByPassword(username, password, databasename); } public void getConnect(String databasename) { mongoClient = new MongoClient("localhost", 27017); this.mongoDatabase = mongoClient.getDatabase(databasename); System.out.println("Connect Success!"); } public void getConnectByPassword(String username,String password,String databasename) { List<ServerAddress> adds = new ArrayList<>(); ServerAddress serverAddress = new ServerAddress("localhost", 27017); adds.add(serverAddress); List<MongoCredential> credentials = new ArrayList<>(); MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(username, databasename, password.toCharArray()); credentials.add(mongoCredential); mongoClient = new MongoClient(adds, credentials); this.mongoDatabase = mongoClient.getDatabase(databasename); System.out.println("Connect Success!"); } public static void insertOne(MongoDatabase mongoDatabase,String collectionname,Document document) { MongoCollection<Document> collection = mongoDatabase.getCollection(collectionname); collection.insertOne(document); System.out.println("Insert document Success!"); } public static void insertMany(MongoDatabase mongoDatabase,String collectionname,List<Document> documents) { MongoCollection<Document> collection = mongoDatabase.getCollection(collectionname); collection.insertMany(documents); System.out.println("Insert documents Success!");
} public static void findAll(MongoDatabase mongoDatabase,String collectionname) { MongoCollection<Document> collection = mongoDatabase.getCollection(collectionname); FindIterable<Document> findIterable = collection.find(); MongoCursor<Document> cursor = findIterable.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); } } public static void find(MongoDatabase mongoDatabase,String collectionname,String key,String value) { MongoCollection<Document> collection = mongoDatabase.getCollection(collectionname); Bson filter = Filters.eq(key, value); FindIterable<Document> findIterable = collection.find(filter); MongoCursor<Document> cursor = findIterable.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); } } public static FindIterable<Document> findReturn(MongoDatabase mongoDatabase,String collectionname,String key,String value) { MongoCollection<Document> collection = mongoDatabase.getCollection(collectionname); Bson filter = Filters.eq(key, value); FindIterable<Document> findIterable = collection.find(filter); return findIterable; } public static void main(String[] args) { mongo_insert m = new mongo_insert("Student");
FindIterable<Document> re = findReturn(m.mongoDatabase, "Student", "name", "scofield"); Document results = re.first(); System.out.println(results.get("score")); } }
|
(2)获取 scofield 的所有成绩成绩信息(只显示 score 列)
JAVA代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class mongo_query {
public static void main(String[] args) { MongoClient mongoClient=new MongoClient("localhost",27017); MongoDatabase mongoDatabase = mongoClient.getDatabase("student"); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); MongoCursor<Document> cursor=collection.find( new Document("name","scofield")). projection(new Document("score",1).append("_id", 0)).iterator(); while(cursor.hasNext()) System.out.println(cursor.next().toJson()); } }
|
4.实验总结
(1)实验完成情况
实验完成率:100%
(2)出现的问题与解决方案
问题1: 使用 MySQL 的 JAVA 客户端编程时出现The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received的错误。
解决: 在MySQL的配置文件下/etc/mysql/mysql.conf.d/mysqld.cnf,取消端口3306的注释,错误得以解决
问题2:用 Redis 的 JAVA 客户端编程(jedis)时报错
解决:我发现我导入的jedis里面需要gson的jar包。可能是我本地没有这个jar包导致的。所以,我换了一个低版本的jedis的jar包,里面不需要gson的jar包。我换了一个2.9.0版本的jedis包,然后程序就运行成功了