驱动在 DM8 安装目录 drivers 下,无需单独下载。JDBC 用 drivers/jdbc/DmJdbcDriver8.jar,jar 名数字对应 JDK 版本,JDK 11 用 DmJdbcDriver11.jar。Python 用 drivers/python/dmPython 源码,需编译安装。
驱动类固定为 dm.jdbc.driver.DmDriver,连接串为 jdbc:dm:// 主机:5236,主机省略时默认 localhost,端口省略时默认 5236。
下面代码在 T_APP_USER 上完成建表、插入、批量插入、查询、更新、删除,连接和语句用 try-with-resources 关闭。
代码 1 JDBC 增删改查
import java.sql.\*;
public class DmJdbcDemo {
  static final String URL = "jdbc:dm://127.0.0.1:5236";
  static final String USER = "SYSDBA";
  static final String PWD = "Dameng123";
  public static void main(String\[] args) throws Exception {
  Class.forName("dm.jdbc.driver.DmDriver");
  try (Connection conn = DriverManager.getConnection(URL, USER, PWD)) {
  createTable(conn);
  insert(conn);
  query(conn);
  update(conn);
  delete(conn);
  }
  }
  static void createTable(Connection conn) throws SQLException {
  try (Statement st = conn.createStatement()) {
  st.execute("DROP TABLE T\_APP\_USER");
  st.execute("CREATE TABLE T\_APP\_USER("
  \+ "ID INT PRIMARY KEY, NAME VARCHAR(50), "
  \+ "AGE INT, CREATED DATETIME)");
  }
  }
  static void insert(Connection conn) throws SQLException {
  String sql = "INSERT INTO T\_APP\_USER(ID,NAME,AGE,CREATED) "
  \+ "VALUES(?,?,?,CURRENT\_TIMESTAMP)";
  try (PreparedStatement ps = conn.prepareStatement(sql)) {
  ps.setInt(1, 1); ps.setString(2, "zhang"); ps.setInt(3, 28);
  ps.executeUpdate();
  for (int i = 2; i <= 5; i++) {
  ps.setInt(1, i);
  ps.setString(2, "user" + i);
  ps.setInt(3, 20 + i);
  ps.addBatch();
  }
  ps.executeBatch();
  }
  }
  static void query(Connection conn) throws SQLException {
  String sql = "SELECT ID,NAME,AGE FROM T\_APP\_USER "
  \+ "WHERE AGE > ? ORDER BY ID";
  try (PreparedStatement ps = conn.prepareStatement(sql)) {
  ps.setInt(1, 25);
  try (ResultSet rs = ps.executeQuery()) {
  while (rs.next()) {
  System.out.println(rs.getInt(1) + " "
  \+ rs.getString(2) + " " + rs.getInt(3));
  }
  }
  }
  }
  static void update(Connection conn) throws SQLException {
  try (PreparedStatement ps = conn.prepareStatement(
  "UPDATE T\_APP\_USER SET AGE=? WHERE ID=?")) {
  ps.setInt(1, 29); ps.setInt(2, 1);
  System.out.println("更新行数:" + ps.executeUpdate());
  }
  }
  static void delete(Connection conn) throws SQLException {
  try (PreparedStatement ps = conn.prepareStatement(
  "DELETE FROM T\_APP\_USER WHERE ID=?")) {
  ps.setInt(1, 5);
  System.out.println("删除行数:" + ps.executeUpdate());
  }
  }
}
代码 2 编译运行(Windows 类路径分隔符为分号,Linux 为冒号)
javac -cp DmJdbcDriver8.jar DmJdbcDemo.java
java -cp .;DmJdbcDriver8.jar DmJdbcDemo
JDBC 默认自动提交。多条语句要作为一个事务时,手动关闭自动提交,异常分支回滚。
代码 3 手动事务
conn.setAutoCommit(false);
try {
  // ... 多条写操作
  conn.commit();
} catch (SQLException e) {
  conn.rollback();
  throw e;
}
参数一律用问号占位配合 setInt、setString,不拼接 SQL,防注入并复用执行计划。
批量写入用 addBatch 加 executeBatch,减少往返。
Connection、Statement、ResultSet 用完即关,try-with-resources 不会漏。
dmPython 遵循 Python DB API 2.0,底层调用 DPI,提供的是源码,需编译。Linux 下先设置 DM_HOME,运行时让解释器能找到 DPI 动态库,系统自带 Python 还要装 python3-devel。
代码 4 Linux 编译安装 dmPython
export DM\_HOME=/home/dmdba/dmdbms
export LD\_LIBRARY\_PATH=\$LD\_LIBRARY\_PATH:\$DM\_HOME/drivers/dpi/
yum install gcc python3-devel
cd \$DM\_HOME/drivers/python/dmPython
python3 setup.py install
Windows 下设置 DM_HOME,安装 Visual C++ Build Tools,进入 drivers/python/dmPython 执行 python setup.py install,并确认 DPI 运行库在 Python 搜索路径中。
代码 5 dmPython 增删改查
import dmPython
conn = dmPython.connect(user='SYSDBA', password='Dameng123',
  server='127.0.0.1', port=5236)
cur = conn.cursor()
cur.execute("DROP TABLE T\_APP\_USER")
cur.execute("CREATE TABLE T\_APP\_USER ("
  "ID INT PRIMARY KEY, NAME VARCHAR(50), "
  "AGE INT, CREATED DATETIME)")
cur.execute("INSERT INTO T\_APP\_USER(ID,NAME,AGE,CREATED) "
  "VALUES(?,?,?,CURRENT\_TIMESTAMP)", (1, 'zhang', 28))
rows = \[(i, 'user%d' % i, 20 + i) for i in range(2, 6)]
cur.executemany("INSERT INTO T\_APP\_USER(ID,NAME,AGE,CREATED) "
  "VALUES(?,?,?,CURRENT\_TIMESTAMP)", rows)
cur.execute("SELECT ID,NAME,AGE FROM T\_APP\_USER "
  "WHERE AGE > ? ORDER BY ID", (25,))
for r in cur.fetchall():
  print(r)
cur.execute("UPDATE T\_APP\_USER SET AGE=? WHERE ID=?", (29, 1))
print("更新行数:", cur.rowcount)
cur.execute("DELETE FROM T\_APP\_USER WHERE ID=?", (5,))
print("删除行数:", cur.rowcount)
conn.commit()
cur.close()
conn.close()
dmPython 默认不自动提交,写操作后必须 commit,否则连接关闭后修改不落库。
参数同样用问号占位,execute 第二个参数传元组,批量用 executemany。
fetchone 取一行,fetchall 取全部,rowcount 为上一次写操作影响的行数。
| 对比项 | Java JDBC | Python dmPython |
|---|---|---|
| 驱动 | drivers/jdbc 下 jar,直接引入 | drivers/python/dmPython 源码编译 |
| 连接 | DriverManager.getConnection | dmPython.connect |
| 语句对象 | Statement / PreparedStatement | cursor |
| 参数 | ? 加 setXxx | ? 加 execute (sql, 元组) |
| 批量 | addBatch / executeBatch | executemany |
| 取结果 | ResultSet.next 与 getXxx | fetchone / fetchall |
| 事务 | setAutoCommit / commit / rollback | autocommit / commit / rollback |
| 现象 | 原因 | 处理 |
|---|---|---|
| 连接超时 | 网络不通、端口未放通、实例未启动 | ping、telnet 主机 5236,查防火墙和进程 |
| failed to initialize ssl | 未配置 SSL 却以 SSL 登录 | SP_SET_PARA_VALUE (2,‘ENABLE_ENCRYPT’,0) 后重启 |
| driver not sequoia compliant | JDK 与驱动 jar 不匹配 | 换对应 JDK 的 DmJdbcDriver |
| import dmPython 找不到动态库 | DPI 不在搜索路径 | LD_LIBRARY_PATH 指向 drivers/dpi |
| Oracle 方言行为不一致 | 迁移自 Oracle | URL 追加?compatibleMode=oracle |
引入驱动 jar 后配置数据源即可,HikariCP、MyBatis 用法与其他数据库一致。主备或守护环境用 dm_svc.conf 配置服务名,URL 中填服务名,不要写死单个节点。
代码 6 数据源配置
spring:
  datasource:
  driver-class-name: dm.jdbc.driver.DmDriver
  url: jdbc:dm://127.0.0.1:5236
  username: SYSDBA
  password: Dameng123
  hikari:
  maximum-pool-size: 15
  connection-timeout: 30000
业务账号按最小权限申请,不直接用 SYSDBA;口令走配置注入,不写进源码。
文章
阅读量
获赞
