Java对数据库基本操作
本实验指导用户使用JDBC实现GaussDB数据库基础操作。
1.基础环境配置 #
1.1 创建GaussDB实例(预计15-20分钟) #
注意:确保区域选择的是北京四, 否则会看到权限错误信息,无法购买数据库。
进入云数据库GaussDB服务,点击左侧的【服务列表】,选择其中【数据库】下的【云数据库GaussDB】。
- 进入云数据库GaussDB,点击页面右上角的【购买数据库实例】按钮。
进入购买页后,根据以下参数信息购买数据库。
主要参数如下,其他请保持默认。
• 计费模式:选择【按需计费】
• 区域:默认的【华北-北京四】
• 实例名称:可以设置为【gauss-hccda】
• 产品类型:基础版
• 数据库引擎版本:选择最新版即可
• 实例类型:集中式
• 部署形态:1主2备
• 性能规格: 通用型(1:4) | 4 vCPUs | 16 GB
说明:如果通用型卖完了, 请选择其它可用的规格,如 独享型(1:4) | 4 vCPUs | 16 GB 等。
• 存储类型、存储空间、磁盘加密保持默认
• 虚拟私有云:选择【vpc-hccda】, 【subnet-hccda】
• 安全组:选择【sg-hccda】
• 管理员密码:设置符合安全要求的root用户密码
确认信息无误后,点击【提交】。
注意:GaussDB实例创建需要20分钟,请耐心等待,可以先去执行其他跟数据库无关的操作。
1.2 创建用户及相应数据库和模式 #
创建用户及相应数据库和模式,用于程序后续配置使用。按下图所示,先进入数据库列表并点击登录对应数据库。
在实例登录页面,选择“自定义登录”页签,在节点信息中,选择角色为“master”的节点, 填写购买GaussDB数据库时填写的密码,单击“测试连接”,如果显示“连接成功”,则可以成功登录实例;勾选“记住密码” 和 选择“SQL执行记录”,最后单击“登录”按钮登录到数据库。
按下图所示,进入角色管理页面,点击“新建角色”按钮,进入角色管理页面。
在新建角色页面,输入角色名称 db_dev,密码设置为 XXXXXX ,此处注意一定勾
选“可以登录”和“可以创建数据库”两个选项,然后点击“保存”按钮。
相关参数:
角色名:db_dev
可以登录:勾选
密码:XXXXXX
可以创建数据库:勾选
按图所示创建 db_dev 角色,密码设置为 XXXXXX,此处注意一定勾选“可以登录”和“可以创建数据库”两个选项。
点击保存后将弹出“SQL预览”窗口,点击确定即可。
完成创建后,将当前连接切换为新创建的用户db_dev,如下图所示,点击“切换连接”按钮。
在弹出窗口,选择“自定义登录”输入刚创建的角色信息和密码,勾选“记住密码”和“命令执行记录”,并点击“登录”。
登录后,点击“新建数据库”
在弹出窗口中,按图示输入参数创建“db_test”数据库。
点击数据库链接“db_test”, 进入库管理页面。
按图所示,点击“新建Schema”,创建“schema_test”模式。
1.3 安装JDK #
至此,数据实例已配置完成,下面进行ECS开发环境基础配置。
首先进入实验室桌面,双击打开【Xfce终端】(请将终端窗口最大化),使用ssh命令远程登录ecs服务器。
ssh root@EIP
相关参数:
公网IP:(以实际分配为准),进入华为云控制台获取ECS的EIP
端口:22
用户名:root (以实际分配为准)
密码:xxxxxx (以实际分配为准)
连接成功,进入终端。
执行以下命令创建代码根目录,并进入该新创建目录。
mkdir /root/db-dev-cert
cd /root/db-dev-cert
在当前路径下,执行以下命令,创建代码结构目录。
mkdir libs
mkdir -p src/expt/db/basic
提示:libs后续用来存放第三方运行依赖库,basic目录下存放本次实验涉及的具体代码。
执行以下命令,下载jdbc驱动,并存放于 libs目录下。
cd /root/db-dev-cert/libs
wget https://repo.huaweicloud.com/repository/maven/com/huaweicloud/gaussdb/opengaussjdbc/503.2.T35/opengaussjdbc-503.2.T35.jar
执行以下命令,下载JDK软件包,并配置环境。
cd /root
wget https://sandbox-experiment-files.obs.cn-north-4.myhuaweicloud.com:443/lab2024/20220525/OpenJDK11U-jdk_x64_linux_openj9_linuxXL_11.0.10_9_openj9-0.24.0.tar.gz
tar -xzvf OpenJDK11U-jdk_x64_linux_openj9_linuxXL_11.0.10_9_openj9-0.24.0.tar.gz
mv jdk-11.0.10+9 /usr/lib/
ln -s /usr/lib/jdk-11.0.10+9/bin/java /usr/local/bin/java
ln -s /usr/lib/jdk-11.0.10+9/bin/javac /usr/local/bin/javac
执行以下命令,验证java运行命令是否就绪:
java -version
回显结果输出如下:
执行以下命令,验证javac运行命令是否就绪:
javac -version
回显结果输出如下:
1.4 配置数据库配置文件 #
配置数据库配置文件(dbconfig.properties):
mkdir /root/db-dev-cert/config
cd /root/db-dev-cert/config
vim dbconfig.properties
输入正确的配置值:
jdbc_driver=com.huawei.opengauss.jdbc.Driver
db_url=jdbc:opengauss://192.168.0.71:8000/db_test
db_user=db_dev
db_password=XXXXXX
currentschema=schema_test
备注: jdbc_driver是驱动的类名,db_url是连接数据库的URL,使用正确的值替换数据库IP, 数据库端口号,数据库名称,如”192.168.0.71:8000” 需修改为当前实际所使用数据库对应的主节点的IP地址(如果不设置成主节点的IP,会导致不能创建表格)和端口;db_test为之前所创建的数据库名称,若未按照之前实验参数创建,需对应匹配修改为真实数据库名称, db_user是连接数据库的用户,db_password是连接数据库的用户对应的密码,currentschema是当前数据库的模式名称。
2.连接数据库 #
使用程序对数据库进行操作之前,需要让程序先建立对数据的连接。本节将使用程序对数据库连接进行实验,并创建一个公共的工具类dbUtils,为后续实践打下基础,方便直接调用。
执行以下命令,在指定目录创建dbUtils.java文件。
cd /root/db-dev-cert/src/expt/db/basic
touch dbUtils.java
使用vi命令,将以下代码内容写入dbUtils.java文件中。
package expt.db.basic;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.Properties;
public class dbUtils {
public static Connection getConnect(String driver, String db_conn_url) {
Connection conn = null;
try {
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
return null;
}
// open connecting
System.out.println("connecting database...");
try {
System.out.println("connection url is: " + db_conn_url);
conn = DriverManager.getConnection(db_conn_url);
System.out.println("connection successfully!");
return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void closeConnect(Connection conn) {
System.out.println("colsing connection...");
try {
conn.close();
System.out.println("connection closed!");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Properties loadProperties() {
InputStream input = null;
Properties prop = new Properties();
try {
input = new FileInputStream("/root/db-dev-cert/config/dbconfig.properties");
// 加载配置文件
prop.load(input);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return prop;
}
public static void printAllRecords(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
for (int i = 0; i < metaData.getColumnCount(); i++) {
System.out.print(metaData.getColumnName(i + 1) + "\t");
}
System.out.println();
while (rs.next()) {
for (int i = 0; i < metaData.getColumnCount(); i++) {
System.out.print(rs.getString(i + 1) + "\t");
}
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void printOneRecord(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
for (int i = 0; i < metaData.getColumnCount(); i++) {
System.out.print(metaData.getColumnName(i + 1) + "\t");
}
System.out.println();
for (int i = 0; i < metaData.getColumnCount(); i++) {
System.out.print(rs.getString(i + 1) + "\t");
}
System.out.println("\ncurrent row number: " + rs.getRow() + "\n");
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行以下命令,在指定目录创建exptConnection.java文件
cd /root/db-dev-cert/src/expt/db/basic
touch exptConnection.java
使用vi命令,将以下代码内容写入exptConnection.java文件中。输入结束后,使用”:wq”保存退出vim编辑。
package expt.db.basic;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class exptConnection {
public static void main(String[] args) {
getConnect();
}
public static Connection getConnect() {
//装载配置文件。
Properties prop = dbUtils.loadProperties();
Connection conn = null;
//读取配置文件中的属性
String jdbcdriver = prop.getProperty("jdbc_driver");
String dburl = prop.getProperty("db_url");
String user = prop.getProperty("db_user");
String password = prop.getProperty("db_password");
String connection_url = dburl + "?user=" + user + "&password=" + password;
//打印连接URL
System.out.println("connection_url: " + connection_url);
/* 驱动注册 */
try {
Class.forName(jdbcdriver);
} catch (Exception e) {
e.printStackTrace();
return null;
}
/* 连接数据库 */
System.out.println("connecting database...");
try {
conn = DriverManager.getConnection(connection_url);
System.out.println("connection successfully!");
return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
注:需要确保配置文件(/root/db-dev-cert/config/dbconfig.properties)已经存在,而且配置值是正确的。
执行以下命令,进行编译:
javac -classpath ../../../ -d . exptConnection.java
编译完成后,会在当前目录下生编译成class数据文件及对应目录结构,参考如下:
yum -y install tree
tree
执行以下命令,运行对应代码文件
java -p /root/db-dev-cert/libs/opengaussjdbc-503.2.T35.jar expt.db.basic.exptConnection
回显结果输出如下:
回显信息末尾出现”connection successfully”,说明依据当前参数已正常连接数据库。
3.创建数据表 #
上一节中完成了对数据库的连接,使得程序能够对数据库实例建立连接。基于此连接建立的基础上,可进行数据库表创建的操作实验。本小节会将该连接代码单独抽取出来,方便后续实验可以重复使用,从而避免每次在编写相关操作代码之前,都拷贝一份连接代码。
执行以下命令,创建exptCreateTable.java文件。
cd /root/db-dev-cert/src/expt/db/basic
touch exptCreateTable.java
使用vi命令,将以下代码内容写入exptCreateTable.java文件中。输入结束后,使用”:wq”保存退出vi编辑。
package expt.db.basic;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class exptCreateTable {
public static void main(String[] args) throws SQLException {
//装载配置文件。
Properties prop = dbUtils.loadProperties();
//读取配置文件中的属性
String jdbcdriver = prop.getProperty("jdbc_driver");
String dburl = prop.getProperty("db_url");
String user = prop.getProperty("db_user");
String password = prop.getProperty("db_password");
String conn_url = dburl + "?user=" + user + "&password=" + password + "¤tSchema=schema_test";
Connection conn = dbUtils.getConnect(jdbcdriver, conn_url);
Statement statement = conn.createStatement();
statement.execute(
"create table test_table (id int, name varchar(10), destination varchar(20), uuid varchar(36))");
System.out.println("execute successfully!");
dbUtils.closeConnect(conn);
}
}
javac -classpath ../../../ -d . exptCreateTable.java
执行以下命令,运行对应代码文件:
java -p /root/db-dev-cert/libs/opengaussjdbc-503.2.T35.jar expt.db.basic.exptCreateTable
回显结果输出如下:
回显信息末尾出现”excute successfully!”,说明正常连接数据库,并成功创建数据表。
4.增删查改数据 #
上一节中完成了对数据库表的创建,现在在上一节的基础上,使用程序在表中进行插入数据,查询并打印数据,修改数据,删除数据的实验。
执行以下命令,创建exptInsert.java文件。
cd /root/db-dev-cert/src/expt/db/basic
touch ExpDataOperation.java
使用vi命令,将以下代码内容写入ExpDataOperation.java文件中。
package expt.db.basic;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class ExpDataOperation {
static Properties prop = new Properties();
static void loadProperties() {
InputStream input = null;
try {
input = new FileInputStream("/root/db-dev-cert/config/dbconfig.properties");
// 加载配置文件
prop.load(input);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws SQLException {
//装载配置文件。
loadProperties();
//读取配置文件中的属性
String jdbcdriver = prop.getProperty("jdbc_driver");
String dburl = prop.getProperty("db_url");
String user = prop.getProperty("db_user");
String password = prop.getProperty("db_password");
String conn_url = dburl + "?user=" + user + "&password=" + password + "¤tSchema=schema_test";
System.out.println("the connection url:" + conn_url);
Connection conn = dbUtils.getConnect(jdbcdriver, conn_url);
/* 插入一条数据 */
Statement statement = conn.createStatement();
statement.execute("INSERT INTO test_table(id, name, destination, uuid) "
+ "values (2, 'zhangsan', 'hangzhou', 123456789)");
System.out.println("插入行数: "+statement.getUpdateCount());
/* 查询并打印数据 */
ResultSet resultSet = null;
PreparedStatement queryStatement=conn.prepareStatement("select * from test_table where id=?;");
queryStatement.setObject(1,2);
resultSet = queryStatement.executeQuery();
dbUtils.printAllRecords(resultSet);
/* 修改一条数据 */
PreparedStatement updateStatement=conn.prepareStatement("update test_table set name=? where id=?");
updateStatement.setObject(1, "wangwu");
updateStatement.setObject(2, 2);
updateStatement.execute();
System.out.println("修改行数:"+updateStatement.getUpdateCount());
/* 删除一条数据 */
PreparedStatement deleteStatement = conn.prepareStatement("delete from test_table where id = ?");
deleteStatement.setObject(1, 2);
deleteStatement.execute();
System.out.println("删除行数:"+deleteStatement.getUpdateCount());
dbUtils.closeConnect(conn);
}
}
执行以下命令,进行编译:
javac -classpath ../../../ -d . ExpDataOperation.java
执行以下命令,运行对应代码文件:
java -p /root/db-dev-cert/libs/opengaussjdbc-503.2.T35.jar expt.db.basic.ExpDataOperation
回显结果输出如下:
回显信息末尾出现"插入行数:1",说明程序中1条数据成功插入表中。
回显信息打印出插入的数据(2,zhangsan,hangzhou),说明查询功能正常。
回显信息末尾出现"修改行数:1",说明程序成功修改1条数据。
回显信息末尾出现"删除行数:1",说明程序成功删除1条数据。
5.批量插入数据 #
在实际场景中,会遇到大量的数据需要入库,此时若是按照之前的方式一次一条插入,将会非常耗时,同时消耗数据库性能,影响其它业务正常运行。因此本节进行批量插入的实验,同时会将和非批量插入方式做一个对比试验,从实际运行数据上来验证批量插入的性能提升。
执行以下命令,创建exptBatchInsert.java文件。
cd /root/db-dev-cert/src/expt/db/basic
touch exptBatchInsert.java
使用vim命令,将以下代码内容写入exptBatchInsert.java文件中。输入结束后,使用”:wq”保存退出vim编辑。
package expt.db.basic;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import java.util.UUID;
public class exptBatchInsert {
static String JDBC_DRIVER = "";
static String conn_url = "";
public static void main(String[] args) throws SQLException {
int current;
//装载配置文件。
Properties prop = dbUtils.loadProperties();
//读取配置文件中的属性
JDBC_DRIVER = prop.getProperty("jdbc_driver");
String dburl = prop.getProperty("db_url");
String user = prop.getProperty("db_user");
String password = prop.getProperty("db_password");
String currentSchema = prop.getProperty("currentschema", "schema_test") ;
conn_url = dburl + "?user=" + user + "&password=" + password + "¤tSchema=" + currentSchema;
System.out.println("the connection url:" + conn_url);
current = insertRecordOnceATime(1, 1000);
insertRecordBatch(current, 1000);
}
public static int insertRecordOnceATime(int begin, int count) {
PreparedStatement preparedStatement;
int index = begin;
try {
Connection conn = dbUtils.getConnect(JDBC_DRIVER, conn_url);
conn.setAutoCommit(true);
String targetQuery = "INSERT INTO test_table(id, name, destination, uuid) VALUES(?, ?, ?, ?)";
preparedStatement = conn.prepareStatement(targetQuery);
long start = System.currentTimeMillis();
for( ; index < begin+count; index++) {
preparedStatement.setInt(1, index);
preparedStatement.setString(2, "name-"+index);
preparedStatement.setString(3, "destination-"+index);
preparedStatement.setString(4, UUID.randomUUID().toString());
long startInternal = System.currentTimeMillis();
preparedStatement.executeUpdate();
System.out.println("each transaction time taken = " + (System.currentTimeMillis() - startInternal) + " ms");
}
long end = System.currentTimeMillis();
System.out.println("total time taken = " + (end - start) + " ms");
System.out.println("avg total time taken = " + (end - start)/ count + " ms");
preparedStatement.close();
dbUtils.closeConnect(conn);
} catch (SQLException ex) {
System.err.println("SQLException information");
while (ex != null) {
System.err.println("Error msg: " + ex.getMessage());
ex = ex.getNextException();
}
}
return index;
}
public static void insertRecordBatch(int begin, int count) {
PreparedStatement preparedStatement;
int index = begin;
try {
Connection conn = dbUtils.getConnect(JDBC_DRIVER, conn_url);
conn.setAutoCommit(true);
String targetQuery = "INSERT INTO test_table(id, name, destination, uuid) VALUES(?, ?, ?, ?)";
preparedStatement = conn.prepareStatement(targetQuery);
for( ; index < begin+count; index++) {
preparedStatement.setInt(1, index);
preparedStatement.setString(2, "name-"+index);
preparedStatement.setString(3, "destination-"+index);
preparedStatement.setString(4, UUID.randomUUID().toString());
preparedStatement.addBatch();
}
long start = System.currentTimeMillis();
int[] inserted = preparedStatement.executeBatch();
long end = System.currentTimeMillis();
System.out.println("total time taken to insert the batch = " + (end - start) + " ms");
System.out.println("total time taken = " + (end - start)/count + " s");
preparedStatement.close();
dbUtils.closeConnect(conn);
System.out.println("row influence number is: " + inserted.length);
} catch (SQLException ex) {
System.err.println("SQLException information");
while (ex != null) {
System.err.println("Error msg: " + ex.getMessage());
ex = ex.getNextException();
}
throw new RuntimeException("Error");
}
}
}
执行以下命令,进行编译:
javac -classpath ../../../ -d . exptBatchInsert.java
执行以下命令,运行对应代码文件:
java -p /root/db-dev-cert/libs/opengaussjdbc-503.2.T35.jar expt.db.basic.exptBatchInsert
回显结果输出如下:
从回显信息中的总耗时可以看出,在1000数据量的情况下,一次一条数据的插入方式的总耗时,比批量插入耗时高出两个数量级。
6.添加游标数据 #
上一节中我们完成了数据库表批量数据的插入,现在继续在上一节产生的数据基础上,来完成本节数据游标实验。
执行以下命令,创建exptCursor.java文件。
cd /root/db-dev-cert/src/expt/db/basic
touch exptCursor.java
使用vi命令,将以下代码内容写入exptCursor.java文件中。输入结束后,使用”:wq”保存退出vi编辑。
package expt.db.basic;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class exptCursor {
public static void main(String[] args) throws SQLException {
PreparedStatement preparedStatement;
try {
//装载配置文件。
Properties prop = dbUtils.loadProperties();
//读取配置文件中的属性
String jdbcdriver = prop.getProperty("jdbc_driver");
String dburl = prop.getProperty("db_url");
String user = prop.getProperty("db_user");
String password = prop.getProperty("db_password");
String conn_url = dburl + "?user=" + user + "&password=" + password + "¤tSchema=schema_test";
System.out.println("the connection url:" + conn_url);
Connection conn = dbUtils.getConnect(jdbcdriver, conn_url);
String targetQuery = "select * from test_table";
preparedStatement = conn.prepareStatement(targetQuery, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.next();
dbUtils.printOneRecord(resultSet);
resultSet.last();
dbUtils.printOneRecord(resultSet);
resultSet.previous();
dbUtils.printOneRecord(resultSet);
resultSet.first();
dbUtils.printOneRecord(resultSet);
System.out.println("is before first: " + resultSet.isBeforeFirst());
resultSet.afterLast();
System.out.println("is after last: " + resultSet.isAfterLast());
resultSet.beforeFirst();
System.out.println("is before first: " + resultSet.isBeforeFirst());
resultSet.next();
dbUtils.printOneRecord(resultSet);
resultSet.absolute(4);
dbUtils.printOneRecord(resultSet);
resultSet.relative(1);
dbUtils.printOneRecord(resultSet);
resultSet.absolute(-2);
dbUtils.printOneRecord(resultSet);
resultSet.relative(-1);
dbUtils.printOneRecord(resultSet);
preparedStatement.close();
dbUtils.closeConnect(conn);
} catch (SQLException ex) {
System.err.println("SQLException information");
while (ex != null) {
System.err.println("Error msg: " + ex.getMessage());
ex = ex.getNextException();
}
}
}
}
执行以下命令,进行编译:
javac -classpath ../../../ -d . exptCursor.java
执行以下命令,运行对应代码文件:
java -p /root/db-dev-cert/libs/opengaussjdbc-503.2.T35.jar expt.db.basic.exptCursor
回显结果输出如下:
从回显打印出的数据信息可以看出,与程序中对应游标各种使用产生效果是一一对应的。同时通过回显的结果,也可以更好的理解游标的使用。
7.分页查询数据 #
上一节中我们完成了对数据库表的创建,现在仍然在批量插入所产生数据的基础上,使用程序进行分页查询实验。
执行以下命令,创建exptPagination.java文件。
cd /root/db-dev-cert/src/expt/db/basic
touch exptPagination.java
使用vi命令,将以下代码内容写入exptPagination.java文件中。输入结束后,使用”:wq”保存退出vi编辑。
package expt.db.basic;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class exptPagination {
public static void main(String[] args) throws SQLException {
int pageNumber = 1; // from 1 to N
int pageSize = 3;
//装载配置文件。
Properties prop = dbUtils.loadProperties();
//读取配置文件中的属性
String jdbcdriver = prop.getProperty("jdbc_driver");
String dburl = prop.getProperty("db_url");
String user = prop.getProperty("db_user");
String password = prop.getProperty("db_password");
String conn_url = dburl + "?user=" + user + "&password=" + password + "¤tSchema=schema_test";
System.out.println("the connection url:" + conn_url);
Connection conn = dbUtils.getConnect(jdbcdriver, conn_url);
if (args.length == 2) {
pageNumber = Integer.parseInt(args[0]);
pageSize = Integer.parseInt(args[1]);
}
pageQueryByCursor(conn, pageNumber, pageSize);
dbUtils.closeConnect(conn);
}
public static void pageQueryByCursor(Connection conn, int pageNumber, int pageSize) {
PreparedStatement preparedStatement;
int startNo = (pageNumber - 1) * pageSize;
int endNo = pageNumber * pageSize;
String targetQuery = "select * from test_table";
try {
preparedStatement = conn.prepareStatement(targetQuery, ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
preparedStatement.setMaxRows(endNo);
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.beforeFirst();
resultSet.relative(startNo);
dbUtils.printAllRecords(resultSet);
preparedStatement.close();
} catch (SQLException ex) {
System.err.println("SQLException information");
while (ex != null) {
System.err.println("Error msg: " + ex.getMessage());
ex = ex.getNextException();
}
}
}
}
执行以下命令,进行编译:
javac -classpath ../../../ -d . exptPagination.java
执行以下命令,运行对应代码文件:
java -p /root/db-dev-cert/libs/opengaussjdbc-503.2.T35.jar expt.db.basic.exptPagination
回显结果输出如下:
从回显信息中可以看到,默认情况下,程序以每页三条记录规格,输出了第一页的记录内容。
若想以每页10条记录规格,输出第100页的内容,可在程序执行时指定页规格和页号两个参数。
执行以下命令,运行对应代码文件:
java -p /root/db-dev-cert/libs/opengaussjdbc-503.2.T35.jar expt.db.basic.exptPagination 100 10
回显结果输出如下:
分页的方式不仅可以使用游标实现,还可以使用SQL语句自身实现,其实现的函数示例代码如下,可以将其替换先前游标实现内容,并予以尝试。
public static void pageQueryByLimitAndOffset(Connection conn, int pageNumber, int pageSize)
{
PreparedStatement preparedStatement;
String targetQuery = "select * from test_table limit ?, ?";
try {
preparedStatement = conn.prepareStatement(targetQuery);
preparedStatement.setInt(1, (pageNumber-1)*pageSize);
preparedStatement.setInt(2, pageSize);
ResultSet resultSet = preparedStatement.executeQuery();
dbUtils.printAllRecords(resultSet);
preparedStatement.close();
} catch (SQLException ex) {
System.err.println("SQLException information");
while (ex != null) {
System.err.println("Error msg: " + ex.getMessage());
ex = ex.getNextException();
}
}
}
8.通过Mybatis连接数据库 #
在 DAS上选择数据库(db_test) 和 模式(schema_test),然后执行下面的SQL创建商品表goods并插入数据:
CREATE TABLE goods (
userid INTEGER PRIMARY KEY,
goodsid INTEGER,
deliveryTime date,
title VARCHAR(100),
description VARCHAR(100),
category VARCHAR(20),
originalPrice FLOAT(3),
price FLOAT(3)
) ;
8.1 准备数据
创建商品表如下图:
执行成功后的日志:
在DAS上执行下面的SQL插入数据:
INSERT INTO goods(goodsid, userid, deliveryTime, title, description, category, originalPrice, price)
values (1,1,'2024-06-21','手机','华为手机','电子产品',5000,6000) ;
INSERT INTO goods(goodsid, userid, deliveryTime, title, description, category, originalPrice, price)
values (2,2,'2024-06-21','手机','小米手机','电子产品',1000,2000) ;
INSERT INTO goods(goodsid, userid, deliveryTime, title, description, category, originalPrice, price)
values (3,3,'2024-06-22','热水器','美的热水器','电器',3000,4000) ;
INSERT INTO goods(goodsid, userid, deliveryTime, title, description, category, originalPrice, price)
values (4,4,'2024-06-26','苹果','红苹果','水果',5,10) ;
INSERT INTO goods(goodsid, userid, deliveryTime, title, description, category, originalPrice, price)
values (5,5,'2024-06-28','桃子','水密桃','水果',10,15) ;
INSERT INTO goods(goodsid, userid, deliveryTime, title, description, category, originalPrice, price)
values (6,6,'2024-06-29','杯子','水杯','日用品',15,30);
INSERT INTO goods(goodsid, userid, deliveryTime, title, description, category, originalPrice, price)
values (7,7,'2024-06-30','空调','格力空调','电器',3000,5000);
插入成功如下图:
8.2 安装Maven
- 在ECS服务器上执行下面的命令下载并安装maven
mkdir -p /root/db-dev-cert/maven
cd /root/db-dev-cert/maven
wget https://sandbox-experiment-files.obs.cn-north-4.myhuaweicloud.com:443/lab2024/hccdp/HCCDP/apache-maven-3.6.0-bin.tar.gz
tar -zxvf apache-maven-3.6.0-bin.tar.gz
ln -s /root/db-dev-cert/maven/apache-maven-3.6.0/bin/mvn /usr/local/bin/mvn
2)执行下面的命令检查maven 是否安装成功 。
mvn -version
备注:确保安装了JDK。
- 执行下面的命令修改maven的配置settings.xml,设置本地库目录和华为仓库。
cd /root/db-dev-cert/maven/apache-maven-3.6.0/conf
vim settings.xml
拷贝下面的配置到settings.xml去设置本地目录(确保ECS服务器上存在本地目录(/root/db-dev-cert/libs))
<localRepository>/root/db-dev-cert/libs</localRepository>
设置华为仓库:
a)拷贝下面的配置到settings.xml的节点下面去增加镜像。
<mirror>
<id>huaweicloud</id>
<mirrorOf>*,!HuaweiCloudSDK</mirrorOf>
<url>https://repo.huaweicloud.com/repository/maven/</url>
</mirror>
b)拷贝下面的配置到settings.xml的< profiles>下面增加profile, 然后使用”:wq”保存settings.xml退出vim编辑。
<profile>
<id>MyProfile</id>
<repositories>
<repository>
<id>HuaweiCloudSDK</id>
<url>https://repo.huaweicloud.com/repository/maven/huaweicloudsdk/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</profile>
8.3 书写代码
1) 创建接口类GoodsMapper。
用来进行数据库操作
mkdir -p /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/mapper
cd /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/mapper
vim GoodsMapper.java
输入下面的内容到文件里:
package com.huawei.guassdb.mapper;
import java.util.List;
import com.huawei.guassdb.pojo.Goods;
public interface GoodsMapper {
Goods selectGoodsByUserId(int goodsid);
List<Goods> getAllGoods();
}
2)创建Goods_Mapper.xml文件。
用来配置SQL与JAVA API的映射,namespace的名称必需与第1步的GoodsMapper名称一样, select节点的id属性与GoodsMapper的方法同名。
执行下面的命令,去创建文件:
cd /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/mapper
vim Goods_Mapper.xml
输入"i"命令插入下面的内容到文件里,然后输入":wq"保存退出:
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.huawei.guassdb.mapper.GoodsMapper"><select id="selectGoodsByUserId" resultType="com.huawei.guassdb.pojo.Goods" parameterType="int">
select * FROM goods WHERE userid = #{userid}</select><select id="getAllGoods" resultType="com.huawei.guassdb.pojo.Goods" >
select * FROM goods
</select></mapper>
3) 创建Goods类。
执行下面的命令,去创建文件:
mkdir /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/pojo
cd /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/pojo
vim Goods.java
输入"i"命令插入下面的内容到文件里,然后输入":wq"保存退出:
package com.huawei.guassdb.pojo;
public class Goods {
private long goodsid;
private long userid;
private String title;
private String deliveryTime;
private String description;
private String category ;
private float originalPrice;
private float price;
public long getGoodsid() {
return goodsid;
}
public void setGoodsid(long goodsid) {
this.goodsid = goodsid;
}
public long getUserid() {
return userid;
}
public void setUserid(long userid) {
this.userid = userid;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public float getOriginalPrice() {
return originalPrice;
}
public void setOriginalPrice(float originalPrice) {
this.originalPrice = originalPrice;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public long getGoodsId() {
return goodsid;
}
public void setGoodsId(long goodsid) {
this.goodsid = goodsid;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return this.title;
}
public String getDeliveryTime() {
return deliveryTime;
}
public void setDeliveryTime(String deliveryTime) {
this.deliveryTime = deliveryTime;
}
@Override
public String toString() {
return "Goods{" + "用户账号=" + userid + ", 产品='" + title + '\'' +", 商品号='" + goodsid + '\'' +
", 产品描述='" + description + "\', 产品类别='" + category + '\'' +
", 出厂价格='" + originalPrice + "\', 市场价格='" + price + '\'' +
"}";
}
}
4)创建配置文件mybatis\mybatis-config.xml
mybatis的核心配置文件,配置数据库连接相关的配置项,以及Mappter等。
执行下面的命令,去创建文件:
mkdir /root/db-dev-cert/mybatisdemo/src/main/java/mybatis
cd /root/db-dev-cert/mybatisdemo/src/main/java/mybatis
vim mybatis-config.xml
输入"i"命令插入下面的内容到文件里,然后输入":wq"保存退出(需要替换正确的数据库IP,数据库端口号, 数据库名称,schema名称,用户名和密码):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.huawei.opengauss.jdbc.Driver"/>
<property name="url" value="jdbc:opengauss://192.168.0.168:8000/db_test?currentSchema=schema_test"/>
<property name="username" value="db_dev"/>
<property name="password" value="XXXXXX"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/huawei/guassdb/mapper/Goods_Mapper.xml"/>
</mappers>
</configuration>
备注:如果修改了本配置文件的值,需要用maven重新编译构建确保配置生效。
5)创建MyBatisUtil.java文件
用来建立数据库会话SqlSession,用它在数据库执行SQL命令。
执行下面的命令,去创建文件:
mkdir /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/util
cd /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/util
vim MyBatisUtil.java
输入"i"命令插入下面的内容到文件里,然后输入":wq"保存退出:
package com.huawei.guassdb.util;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
6)创建TestMyBatis类
Main入口类,用来测试和打印数据在屏幕上。
执行下面的命令,去创建文件:
cd /root/db-dev-cert/mybatisdemo/src/main/java/com/huawei/guassdb/util
vim TestMyBatis.java
输入"i"命令插入下面的内容到文件里,然后输入":wq"保存退出:
package com.huawei.guassdb.util;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.huawei.guassdb.mapper.GoodsMapper;
import com.huawei.guassdb.pojo.Goods;
public class TestMyBatis {
public static void main(String[] args) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
try {
System.out.println("**********查询一个商品******************");
GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
Goods goods = mapper.selectGoodsByUserId(1);
System.out.println(goods);
System.out.println("**********所有商品**********************");
List<Goods> allgoods = mapper.getAllGoods();
for (int i = 0; i < allgoods.size(); i ++ ) {
System.out.println(allgoods.get(i));
}
System.out.println("*****************结束*******************");
System.out.println("----finished successfully!----");
} finally {
sqlSession.close();
}
System.exit(0);
}
}
8.4 编译构建并运行程序打印数据
1)创建pom.xml
执行下面的命令,去创建文件:
cd /root/db-dev-cert/mybatisdemo/
vim pom.xml
输入"i"命令插入下面的内容到文件里,然后输入":wq"保存退出:
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.huawei.gaussdb</groupId>
<artifactId>gaussdb-project</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!-- 添加junit依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>com.huaweicloud.gaussdb</groupId>
<artifactId>opengaussjdbc</artifactId>
<version>503.2.T35</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
2)在源代码的根目录执行下面的mvn命令编译构建jar文件。
cd /root/db-dev-cert/mybatisdemo/
mvn clean install
- 运行下面的 find命令检查是否成功产生gaussdb-project-1.0.jar文件。
cd /root/db-dev-cert/
find . -type f -name gaussdb-project-1.0.jar
- 确保mybatis JAR和 opengaussjdbc JAR文件存在。
cd /root/db-dev-cert/
find . -type f -name mybatis-3.5.9.jar
find . -type f -name opengaussjdbc-503.2.T35.jar
5)运行下面的java命令执行程序并打印数据。
cd /root/db-dev-cert/mybatisdemo
java -classpath .:/root/db-dev-cert/mybatisdemo/target/gaussdb-project-1.0.jar:/root/db-dev-cert/libs/org/mybatis/mybatis/3.5.9/mybatis-3.5.9.jar:/root/db-dev-cert/libs/com/huaweicloud/gaussdb/opengaussjdbc/503.2.T35/opengaussjdbc-503.2.T35.jar com.huawei.guassdb.util.TestMyBatis
正确的打印结果如下图: