在这里插入图片描述

前言

  数据库访问是数据库应用系统中非常重要的组成部分,DM 作为一个通用数据库管理系统,提供了多种数据库访问接口,包括 ODBC、JDBC、DPI 等方式。本开发指南详细介绍了 DM 的各种访问接口、相应开发环境的配置、以及一些开发用例。本指南的主要读者是从事过数据库应用系统开发,并具有 SQL 使用基础的程序员。开发一个应用系统,需要对其使用的数据库管理系统所具有的功能、性能、特性有较深入的了解。DM 作为一个通用的数据库管理系统,具有非常丰富的功能和特色。

测试工具说明
开发工具IDEA 2024
数据库版本DM8
JDBC驱动包DmJdbcDriver18
JDK环境17

一、概述

1.1 JDBC介绍

  在实际项目开发中,操作数据库是必不可少的,常用的操作数据库的框架,如:MyBatis、JdbcTemplate等有很多。但是,无论使用哪种框架操作数据库,最底层的api实现都是JDBC,就是说,在开发中,JDBC有着举足轻重的地位,是最基础也是最核心的。

  JDBC 是 Java 应用程序与数据库的接口规范,旨在让各数据库开发商为 Java 程序员提供标准的数据库应用程序编程接口,其定义了一个跨数据库、跨平台的通用 SQL 数据库 API。DM JDBC 驱动程序是 DM 数据库的 JDBC 驱动程序,它是一个能够支持基本SQL功能的通用应用程序编程接口,支持一般的SQL数据库访问。通过 JDBC 驱动程序,用户可以在应用程序中实现对 DM 数据库的连接与访问,JDBC 驱动程序的主要功能包括:建立与DM数据库的连接、转接发送SQL语句到数据库以及处理并返回语句执行结果。

  利用JDBC 驱动程序进行编程的一般步骤为:

序号步骤说明
1获取 java.sql.Connection对象利用 DriverManager 或者数据库源来建立同数据库的连接。
2创建 java.sql.Statement 对象这里也包含了 java.sql.PreparedStatement 和 java.sql.CallableStatement对象。
利用连接对象的创建语句对象的方法来创建,在创建过程中根据需要来设置结果集的属性。
3操作数据库操作数据库分为两种情况,更新操作和查询操作。
查询操作执行完成后会得到一个 java.sql.ResultSet 对象,可以操作该对象来获得指定列的信息。
4释放资源操作完成之后,用户需要释放系统资源,主要是关闭结果集、关闭语句对象,释放连接。

1.2 建立JDBC连接

  获得 JDBC 的连接对象,是通过驱动管理器 DriverManager 的 getConnection 方法来建立。若是想要用 Java 连接达梦,需要使用DM JDBC 驱动,其位于 DM 安装目录 /dmdbms/drivers/jdbc 下,将其路径添加到项目工程下,也可以通过maven等方式将对应的依赖引入,相关配置如下:

<!-- https://mvnrepository.com/artifact/com.dameng/DmJdbcDriver18 -->
<dependency>
	<groupId>com.dameng</groupId>
	<artifactId>DmJdbcDriver18</artifactId>
    <version>${dm.version}</version>
</dependency>

注意:使用 JDBC 驱动时,需要使用和服务器端 DM 数据库相近的版本,相隔时间太久的版本,可能出现部分功能无法适配的情况。达梦的 JDBC 驱动目前有三个版本:DmJdbcDriver16.jar、DmJdbcDriver17.jar、DmJdbcDriver18.jar,分别对应 jdk 1.6、jdk 1.7、jdk 1.8 及以上版本,请根据开发环境选择合适的 DM JDBC 驱动包。

  建立配置文件 jdbc.properties文件,用来存放数据库连接配置。properties 文件是Java 支持的一种配置文件类型,将此文件直接放在 /src/main/resources 目录下,不然后面执行可能找不到此配置文件!

# 定义 DM JDBC 驱动串
db.driverClassName=dm.jdbc.driver.DmDriver
# 定义 DM URL 连接串
db.url=jdbc:dm://localhost:5236
# 定义连接用户名
db.user=SYSDBA
# 定义连接用户口令
db.password=SYSDBA

二、基础操作示例

  在DM数据库中,表是用于存储结构化数据的核心组件,其基本结构是由行和列组成,每个表具有唯一名称,用于在数据库中标识它。表中的每个列表示数据的一个属性,每一行表示一个完整的数据记录。表是DM数据库中最基本的存储单元,所有的数据操作都围绕表展开。数据操作主要分为两个方面,一个是更新操作,例如更新数据库、删除一行、创建一个新表等;另一个就是查询操作,执行完查询之后,会得到一个 java.sql.ResultSet 对象,可以操作该对象来获得指定列的信息、读取指定行的某一列的值。
mage

2.1 DM 连接示例

  连接数据库是一项非常重要的功能,这里讲介绍如何连接 DM 数据库。创建工具类 DmJdbcHelperUtil.java,之后的增删改查操作可直接导入这个工具类完成获取连接,释放资源的操作,很方便!废话就不多说,直接上代码,如下所示:

import cn.hutool.setting.dialect.Props;
import cn.hutool.setting.dialect.PropsUtil;
import java.sql.*;

public final class DmJdbcHelperUtil {
    /**
     * 获取连接的方法. 通过读取配置文件从数据库服务器获取一个连接.
     */
    public static Connection getDmJdbcConnection() {
        Props props = PropsUtil.get("jdbc.properties");
        // 定义DM JDBC驱动串
        String jdbcString = props.getStr("db.driverClassName");
        // 定义DM URL连接串
        String urlString = props.getStr("db.url");
        // 定义连接用户名
        String userName = props.getStr("db.user");
        // 定义连接用户口令
        String password = props.getStr("db.password");

        // 定义连接对象
        Connection connection = null;
        try {
            // 1、加载 JDBC 驱动程序(对应的 Driver 实现类中有注册驱动的静态代码块)
            System.out.println("加载 JDBC 驱动...");
            Class.forName(jdbcString);

            // 2、通过 DriverManager 的 getConnection() 方法获取数据库连接
            System.out.println("连接 DM 数据库...");
            connection = DriverManager.getConnection(urlString, userName, password);
            connection.setAutoCommit(true);
            System.out.println("[SUCCESS]conn database");

        } catch (Exception exp) {
            System.out.println("[FAIL]conn database:" + exp.getMessage());
        }
        return connection;
    }

    /**
     * 释放资源,关闭 ResultSet、Statement、Connection
     */
    public static void release(ResultSet resultSet, Statement statement, Connection conn) throws SQLException {
        if (resultSet != null) {
            resultSet.close();
        }

        if (statement != null) {
            statement.close();
        }

        if (conn != null) {
            conn.close();
        }
    }
}

  运行后控制台输出如下图所示:

mage

  在操作完成之后,用户需要释放系统资源,主要是关闭结果集、关闭语句对象,释放连接。当然,这些动作也可以由 JDBC 驱动程序自动执行,但由于 Java 语言的特点,这个过程会比较慢(需要等到 Java 进行垃圾回收时进行),容易出现意想不到的问题。

2.2 表的创建与管理

  DM数据库使用SQL语句来创建和管理表。创建表的基本语法是 CREATE TABLE 语句,后跟表名和列定义。列定义包括列名、数据类型和约束条件。例如:

@Test
public void createTable() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 创建表语句
    String createSql = "CREATE TABLE city ( id CHAR(3) NOT NULL, name VARCHAR(40) NULL, region INT NULL );";
    // 创建语句对象
    PreparedStatement preparedStatement = conn.prepareStatement(createSql);
    // 执行语句
    preparedStatement.executeUpdate();
    // 关闭语句
    DmJdbcHelperUtil.release(null, preparedStatement, conn);
}

  创建表后,可以使用 ALTER TABLE 语句对表进行修改。例如,添加新列、修改列的数据类型、更改约束条件等。删除表可以使用 DROP TABLE 语句,但需要谨慎操作,因为删除表将永久删除表中的所有数据。

2.3 数据的基本操作

插入数据

  在表中插入数据使用 INSERT INTO 语句,指定表名和要插入的数据。例如:

INSERT INTO city(id, name, region) VALUES('BJ', '北京', 1); 
INSERT INTO city(id, name, region) VALUES('SJZ', '石家庄', 1); 
INSERT INTO city(id, name, region) VALUES('SH', '上海', 2); 
INSERT INTO city(id, name, region) VALUES('NJ', '南京', 2); 
INSERT INTO city(id, name, region) VALUES('GZ', '广州', 3); 
INSERT INTO city(id, name, region) VALUES('HK', '海口', 3); 
INSERT INTO city(id, name, region) VALUES('WH', '武汉', 4); 
INSERT INTO city(id, name, region) VALUES('CS', '长沙', 4); 
INSERT INTO city(id, name, region) VALUES('SY', '沈阳', 5); 
INSERT INTO city(id, name, region) VALUES('XA', '西安', 6); 
INSERT INTO city(id, name, region) VALUES('CD', '成都', 7);
@Test
public void insertTable() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 创建表语句
    String insertSql = "INSERT INTO city(id, name, region) VALUES('BJ', '北京', 1)";
    // 创建语句对象
    Statement statement = conn.createStatement();
    // 执行语句
    statement.execute(insertSql);
    // 关闭语句
    DmJdbcHelperUtil.release(null, statement, conn);
    System.out.println("插入成功");
}

  在连接建立后,需要对数据库进行访问,执行命令或是SQL语句,可以通过 Statement 对象执行静态SQL语句并返回其生成结果。但 Statement 对象执行SQL语句存在SQL注入风险,为防范 SQL注入,需要用 PreparedStatement 取代 Statement。

@Test
public void insertTable() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 创建表语句
    String insertSql = "INSERT INTO city(id, name, region) VALUES('BJ', '北京', 1)";
    // 创建语句对象
    PreparedStatement preparedStatement = conn.prepareStatement(insertSql);
    // 执行语句
    preparedStatement.executeUpdate();
    // 关闭语句
    DmJdbcHelperUtil.release(null, preparedStatement, conn);
    System.out.println("插入成功");
}

删除数据

@Test
public void deleteTable() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 删除数据语句
    String deleteSql = "delete from city where id = 'BJ'";
    // 创建语句对象
    PreparedStatement preparedStatement = conn.prepareStatement(deleteSql);
    // 执行语句
    preparedStatement.executeUpdate();
    DmJdbcHelperUtil.release(null, preparedStatement, conn);
    System.out.println("删除成功");
}

修改数据

@Test
public void updateTable() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 更新数据语句
    String updateSql = "update city set name = '北京_BJ' where id = 'BJ'";
    // 创建语句对象
    PreparedStatement preparedStatement = conn.prepareStatement(updateSql);
    // 执行语句
    preparedStatement.executeUpdate();
    // 关闭语句
    DmJdbcHelperUtil.release(null, preparedStatement, conn);
    System.out.println("更新成功");
}

查询数据

  查询表中的数据使用SELECT语句,可以指定要查询的列和查询条件。处理查询结果集,获取当前光标指向行中的数据,有三种方式,如下所示:

@Test
public void queryTable() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 查询语句
    String querySql = "SELECT * FROM city";
    // 创建语句对象
    PreparedStatement preparedStatement = conn.prepareStatement(querySql);
    // 执行查询
    ResultSet resultSet = preparedStatement.executeQuery();
    // 显示结果集
    displayResultSet(resultSet);
    // 关闭
    DmJdbcHelperUtil.release(resultSet, preparedStatement, conn);
}

/**
 * 处理查询结果集。
 * 
 * 获取当前光标指向行中的数据,有三种方式:
 * 
 * 第一种方式:根据字段下标获取。不管数据库表中的字段是什么类型,都以字符串方式取出。
 * 第二种方式:通过结果集中字段名称获取数据,该方式的程序更加健壮,建议使用。
 * 第三种方式:通过特定类型获取数据。该方式可以节省类型转换花费的性能,程序更加健壮,性能更高,推荐使用
 *
 */
private void displayResultSet(ResultSet resultSet) throws SQLException {
    // 将光标向前移动一行,如果指向当前行有记录,则返回true,若指向当前行无记录,返回false
    while (resultSet.next()) {
        /*
         * 第一种方式
         */
        String id1 = resultSet.getString(1);
        String name1 = resultSet.getString(2);
        System.out.println("id1:" + id1 + ",名称1:" + name1);

        /*
         * 第二种方式
         */
        String id2 = resultSet.getString("id");
        String name2 = resultSet.getString("name");
        System.out.println("id2:" + id2 + ",名称2:" + name2);

        /*
         * 第三种方式
         */
        String id3 = resultSet.getString("id");
        String name3 = resultSet.getString("name");
        System.out.println("id3:" + id3 + ",名称3:" + name3);
    }
}

绑定变量示例

  上面提到为防范 SQL 注入,需要用 PreparedStatement 对象执行 SQL 语句。PreparedStatement 执行 SQL 语句中的参数用(?)表示,调用PreparedStatement 对象的 setXXX() 方法来设置这些参数,setXXX() 方法有两个参数,第一个参数是要设置的SQL语句中的索引(从1开始),第二个是设置的SQL语句中参数的值。调用 executeQuery() 返回ResultSet对象,调用 executeUpdate() 执行更新操作,包括增、删、修改等。

@Test
public void preparedStatementTest() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 更新数据语句
    String updateSql = "update city set name = ? where id = ?";
    // 创建语句对象
    PreparedStatement preparedStatement = conn.prepareStatement(updateSql);
    // 通过连接对象和修改语句的模板,创建 java.sql.PreparedStatement 对象
    preparedStatement.setString(1, "北京_BJ");
    preparedStatement.setString(2, "BJ");
    // 执行语句
    preparedStatement.executeUpdate();
    // 关闭语句
    DmJdbcHelperUtil.release(null, preparedStatement, conn);
    System.out.println("更新成功");
}

2.4 元数据MetaData

  DatabaseMetaData 用于获取数据库的元数据信息,包括表名、表的索引、数据库产品的名称和版本、数据库支持的操作等等。它是Java Database Connectivity(JDBC)的一部分,为开发人员提供了访问数据库元数据的便捷途径。

获取数据库的元信息

public static void getDatabaseMetaData() throws SQLException {
    Connection connection = DmJdbcHelperUtil.getDmJdbcConnection();
    // 获取DatabaseMetaData对象
    DatabaseMetaData metaData = connection.getMetaData();

    // 打印数据库的一些基本信息
    System.out.println("数据库名称: " + metaData.getDatabaseProductName());
    System.out.println("数据库版本: " + metaData.getDatabaseProductVersion());
    System.out.println("数据库的主版本:" + metaData.getDatabaseMajorVersion());
    System.out.println("数据库的小版本:" + metaData.getDatabaseMinorVersion());
    System.out.println("数据库支持的SQL语法: " + metaData.getSQLKeywords());
    System.out.println("JDBC驱动名称: " + metaData.getDriverName());
    System.out.println("JDBC驱动版本: " + metaData.getDriverVersion());
    System.out.println("数据库已知的用户: " + metaData.getUserName());
    System.out.println("数据库的系统函数的逗号分隔列表: " + metaData.getSystemFunctions());
    System.out.println("数据库的时间和日期函数的逗号分隔列表: " + metaData.getTimeDateFunctions());
    System.out.println("数据库的字符串函数的逗号分隔列表: " + metaData.getStringFunctions());
    System.out.println("数据库供应商用于 'schema' 的首选术语: " + metaData.getSchemaTerm());
    System.out.println("数据库URL: " + metaData.getURL());
    System.out.println("是否允许只读:" + metaData.isReadOnly());
    System.out.println("驱动程序的名称:" + metaData.getDriverName());
    System.out.println("驱动程序的版本:" + metaData.getDriverVersion());
}

获取数据库的所有表

public static void getTableList() throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 获取Meta信息对象
    DatabaseMetaData meta = conn.getMetaData();
    // 数据库所有者的用户名,一般将它设置为 null。
    String schemaPattern = meta.getUserName();
    // 检索的表的名称,这里设置null,则代表检索全部的表
    String tableNamePattern = null;
    // 想要检索的表的类型
    String[] types = {"TABLE"};
    ResultSet resultSet = meta.getTables(null, schemaPattern, tableNamePattern, types);
    while (resultSet.next()) {
        System.out.println("表名: " + resultSet.getString("TABLE_NAME"));
        System.out.println("注释:" + resultSet.getString("REMARKS"));
    }
}

列出表的所有字段

public static void getColumnList(String tableName) throws SQLException {
    Connection conn = DmJdbcHelperUtil.getDmJdbcConnection();
    // 获取Meta信息对象
    DatabaseMetaData meta = conn.getMetaData();
    // 数据库的用户
    String schemaPattern = meta.getUserName();
    // 表名
    String tableNamePattern = tableName;//
    // 转换为大写
    if (null != tableNamePattern) {
        tableNamePattern = tableNamePattern.toUpperCase();
    }
    String columnNamePattern = null;
    ResultSet resultSet = meta.getColumns(null, schemaPattern, tableNamePattern, null);
    while (resultSet.next()) {
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        int colNum = resultSetMetaData.getColumnCount();
        for (int i = 1; i <= colNum; i++) {
            // 列名
            // String name = resultSetMetaData.getColumnLabel(i);
            System.out.println("表名:" + resultSet.getString("TABLE_NAME"));
            System.out.println("列名:" + resultSet.getString("COLUMN_NAME"));
            System.out.println("字段类型:" + resultSet.getString("TYPE_NAME"));
            System.out.println("列大小:" + resultSet.getLong("COLUMN_SIZE"));
            System.out.println("是否为空:" + resultSet.getInt("NULLABLE"));
            System.out.println("注释:" + resultSet.getString("REMARKS"));
            System.out.println("默认值:" + resultSet.getString("COLUMN_DEF"));
            System.out.println("是否自递:" + "YES".equalsIgnoreCase(resultSet.getString("IS_AUTOINCREMENT")));
        }
    }
}

三、附录

3.1 数据类型映射

DM 数据类型JAVA数据类型
bit、booleanboolean
tinyintshort
smallintint
intlong
bigintfloat
float、doubledouoble
decimalBigdecimal
char、varchar、VARCHAR2String
binary、varbinaryByte[]
dateDate
timeTime

3.2 JDBC-API详解

  JDBC API是Java语言访问数据库的标准API,它定义了一组类和接口,用于封装数据库访问的细节,由于 DM JDBC 驱动遵照 JDBC 标准规范设计与开发,JDBC 接口函数较多,这里仅列出了 DM JDBC 主要接口和函数。

java.sql.DriverManager

  用于管理驱动程序、并可与数据库建立连接,如下表所示。

主要函数说明
getConnection获取数据库连接对象
setLoginTimerout设置登录超时时间
registerDriver注册驱动
deregisterDriver卸载驱动

java.sql.Connection

  数据库连接类,作用是管理执行数据库的连接。可用于提交和回滚事务、创建Statement对象等操作,如下表所示。

主要函数说明
createStatement创建一个sql执行对象:Statement
setAutoCommit设置自动提交
close关闭数据库连接
commit执行事务的提交操作
rollback执行事务的回滚操作

java.sql.Statement

  用于向数据库发送要执行的sql语句(增删改查)并可访问结果,如下表所示。

主要函数说明
execute运行 SQL 语句
executeQuery执行一条返回 ResultSet 的 SQL 语句
executeUpdate执行 INSERT、UPDATE、DELETE 或一条没有返回数据集的 SQL 语句
getResultSet用于得到当前 ResultSet 的结果

java.sql.ResultSet

  是 JDBC 中最重要的结果集对象,主要用于查询关于某个表的信息或一个查询的结果,如下表所示。

主要函数说明
getXxx获取指向行、特定列的内容
absolute将结果集的记录指针移动到指定行
next将结果集的记录指针定位到下一行。如果没有剩余行,则返回 false。
last将结果集的记录指针定位到最后一行
close释放 ResultSet 对象
getMetaData返回 ResultSetMetaData 对象。

java.sql.DatabaseMetaData

  有关整个数据库的信息,如表名、表的索引、数据库产品的名称和版本等。用于获取数据库元数据信息的类,如模式、表、权限、列、存储过程等信息,如下表所示。

主要函数说明
getCatalogs获取该数据库中的信息目录列表。
getTables获取指定参数的表信息
getColumns获取指定表的列信息
getPrimaryKeys获取指定表的主键信息
getImportedKeys获取指定表的外键列信息
getSQLKeywords获取数据库支持的SQL语法
getDriverName获得所连接的数据库驱动程序的名称。
getTypeInfo获取当前数据库的数据类型信息
getExportedKeys获取制定表的外键信息

java.sql.ResultSetMetaData

  用于获取结果集元数据信息的类,如列数、列名、列的数据类型、列大小等信息,如下表所示。

主要函数说明
getColumnCount获取数据集中的列数
getColumnName获取数据集中指定的列名
getColumnLabel获取数据集中指定的标签
getColumnType获取数据集中指定的数据类型
isCurrency如果此列包含带有货币单位的一个数字,则返回 true。
isReadOnly如果此列为只读,则返回 true。
isAutoIncrement如果此列自动递增,则返回 true。这类列通常为主键,而且始终是只读的。

四、总结

  以上就是使用Java连接DM数据库的完整流程和操作步骤,为了更直观地展示利用JDBC驱动程序进行编程的过程,这里使用 mermaid 语法绘制以下流程图:

1、加载驱动
2、创建连接(Connection)
3、创建句柄(Statement)
4、执行操作
5、结果处理(ResultSet)
6、关闭连接

  通过上述步骤,可以成功配置 Java 程序以连接DM数据库。理解每一步的意义,并运行示例代码,将掌握数据库操作的基本要领。希望在后续的学习与实践中,能进一步深入理解数据库的使用,提升自己的开发技能,加油!

image

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部