Skip to content

informat.jdbc 数据库操作

概述

使用informat.jdbc对象进行数据库相关操作

INFO

  • 连接MYSQL、SQLSERVER、DB2、Oracle等数据库,需要下载对应的jdbc驱动。
  • 目录:{织信安装目录}/instance/informat-biz/libs

createConnection

创建数据库连接

javascript
informat.jdbc.createConnection(connection)

TIP

  • 连接创建不成功会抛出异常
  • 设置了autoCommit等于true时,在执行update、insert、delete语句时将会自动提交事务
  • 执行过程中出错会自动回滚
  • 在脚本执行结束后,创建的连接会自动关闭
参数类型描述
connectionConnectionInfo数据库连接信息

返回值

返回数据库连接对象Connection,使用此对象可进行数据库的添查删改操作

示例

javascript
const connection = informat.jdbc.createConnection({
    dburl: 'jdbc:oracle:thin:@host/XE',
    dbuser: 'user',
    dbpassword: 'pass',
    driverClassName: 'oracle.jdbc.driver.OracleDriver',
    autoCommit: false
})
connection.select('select * form table', (row) => {
    console.log(row.getString(1))
})

Connection

select

执行查询,如果查询失败会抛出异常

javascript
connection.select(sql, handler, ...args)
参数类型描述
sqlString查询的SQL
handler(ResultSet)Function查询结果回调函数
args...Object查询的参数

示例1

javascript
//查询 user 表中name等于tom的数据
connection.select('select * from user where name=?', (rs) => {
    console.log(rs.getString('name'))
}, 'tom')

示例2 使用like

javascript
//查询 user 表中name包含tom的数据
connection.select('select * from user where name like concat(' % ',?,' % ')', (rs) => {
    console.log(rs.getString('name'))
}, 'tom')

示例3 使用in

javascript
//查询 user 表中name是tom或jerry的数据
connection.select('select name from user where name in(?,?)', (rs) => {
    console.log(rs.getString('name'))
}, 'tom', 'jerry')

insert

执行插入,如果插入失败会抛出异常

javascript
connection.insert(sql, returnAutoGeneratedKeys, ...args)
参数类型描述
sqlString查询的SQL
returnAutoGeneratedKeysBoolean是否返回自增的主键ID
args...Object插入的参数

返回值

类型为Integer

如果设置了returnAutoGeneratedKeys为true,并且执行的操作为insert则返回最后插入数据的自增ID

示例

javascript
connection.insert('insert into user(name,age) values (?, ?)', true, 'tom', 10)

update

执行更新或者删除, 如果更新或者删除失败会抛出异常

javascript
connection.update(sql, ...args)
参数类型描述
sqlString查询的SQL
args...Object更新的参数

返回值 类型为Integer

返回更新或删除成功的记录条数

示例

javascript
connection.update('update user set age=?', 10)
javascript
connection.update('delete from user where age=?', 10)

commit

提交事务,如果提交事务失败会抛出异常

javascript
connection.commit()

rollback

回滚事务,如果回滚事务失败会抛出异常

javascript
connection.rollback()

callProcedure

执行存储过程,适用于只有IN参数的场景

javascript
connection.callProcedure(sql, ...args)
参数类型描述
sqlString存储过程调用语句
args...ObjectIN参数(按顺序传入,支持null)

TIP

  • callProcedure 只支持IN参数,不返回OUT参数值
  • 适用于只执行操作不需要获取返回值的场景
  • 如果需要获取OUT/INOUT参数的返回值,请使用 callProcedureFull

示例1 - 无参数存储过程

javascript
var conn = informat.jdbc.systemConnection();
// 调用无参数的存储过程
conn.callProcedure('CALL update_all_status()');

示例2 - 带IN参数的存储过程

javascript
var conn = informat.jdbc.systemConnection();
// 调用带参数的存储过程,按顺序传入参数
conn.callProcedure('CALL insert_user(?, ?, ?)', 'tom', 25, 'developer');

示例3 - PostgreSQL类型转换

javascript
var conn = informat.jdbc.systemConnection();
// PostgreSQL需要显式类型转换
conn.callProcedure('CALL update_user_status(?, CAST(? AS INTEGER))', 'u001', 1);

callProcedureFull

执行存储过程,支持IN、OUT、INOUT参数以及结果集处理

javascript
connection.callProcedureFull(sql, params, handler)
参数类型描述
sqlString存储过程调用语句
paramsList<ProcParam>参数数组(支持IN/OUT/INOUT)
handler(ResultSet)Function结果集回调函数(必填,处理返回的结果集数据)

注意

  • handler参数是必填的,用于处理存储过程返回的结果集
  • 如果存储过程不返回结果集,handler函数体可以为null,但参数必须提供
  • OUT/INOUT参数的返回值通过方法返回的Object对象获取,结果集数据通过handler处理

参数对象结构

javascript
// IN参数
{ 
    value: '参数值',     // 参数值
    sqlType: 4,        // SQL类型(PostgreSQL当参数值为数值时必填,否则需要在sql中进行显式类型转换)
    isOut: false       // 标记为IN参数
}

// OUT参数(仅MySQL、Oracle等支持,PostgreSQL不支持纯OUT)
{ 
    name: '参数名',      // 用于返回值的键名(非必填)
    sqlType: 4,        // SQL类型(必填,见下方类型表)
    isOut: true,       // 标记为OUT参数
    isOutOnly: true    // true=纯OUT
}

// INOUT参数
{ 
    name: '参数名',      // 用于返回值的键名(非必填)
    value: 初始值,       // 输入值(可以是null)
    sqlType: 4,        // SQL类型(必填)
    isOut: true,       // 标记为INOUT
    isOutOnly: false   // false=INOUT
}

SQL类型常量表

数据库类型sqlType值说明
BIT-7位类型
TINYINT-6微整数(8位)
SMALLINT5短整数(16位)
INTEGER4整数(32位)
BIGINT-5长整数(64位)
FLOAT6浮点数
REAL7单精度浮点数
DOUBLE8双精度浮点数
NUMERIC2精确数值
DECIMAL3十进制数
CHAR1定长字符串
VARCHAR12变长字符串
LONGVARCHAR-1长文本
NCHAR-15Unicode定长字符串
NVARCHAR-9Unicode变长字符串
LONGNVARCHAR-16Unicode长文本
DATE91日期
TIME92时间
TIMESTAMP93时间戳
TIME_WITH_TIMEZONE2013带时区的时间
TIMESTAMP_WITH_TIMEZONE2014带时区的时间戳
BINARY-2定长二进制数据
VARBINARY-3变长二进制数据
LONGVARBINARY-4长二进制数据
BLOB2004二进制大对象
CLOB2005字符大对象
NCLOB2011Unicode字符大对象
BOOLEAN16布尔值
ROWID-8行标识符
NULL0SQL NULL值
OTHER1111其他类型(PostgreSQL游标可用此类型)
JAVA_OBJECT2000Java对象
DISTINCT2001用户自定义类型
STRUCT2002SQL结构类型
ARRAY2003SQL数组类型
REF2006SQL引用类型
DATALINK70数据链接类型
REF_CURSOR2012Oracle游标类型
SQLXML2009XML类型

常用类型速查

数值类型:

  • 整数: TINYINT(-6) SMALLINT(5) INTEGER(4) BIGINT(-5)
  • 小数: FLOAT(6) DOUBLE(8) NUMERIC(2) DECIMAL(3)

字符类型:

  • 普通字符: CHAR(1) VARCHAR(12) LONGVARCHAR(-1)
  • Unicode字符: NCHAR(-15) NVARCHAR(-9) LONGNVARCHAR(-16)

日期时间:

  • DATE(91) TIME(92) TIMESTAMP(93)

二进制:

  • BINARY(-2) VARBINARY(-3) BLOB(2004)

特殊类型:

  • BOOLEAN(16) OTHER(1111) REF_CURSOR(2012)

返回值

类型为Object,包含所有OUT/INOUT参数的键值对:

  • 如果设置了name,使用name作为键
  • 否则使用out1out2等作为键

handler回调函数

javascript
function(resultSet) {
    // resultSet 是 ResultSet 对象
    // 可以使用 getString、getInt 等方法获取数据
}

示例1 - MySQL: 基本INOUT参数

javascript
var conn = informat.jdbc.createConnection({
    dburl: 'jdbc:mysql://localhost:3306/mydb',
    dbuser: 'root',
    dbpassword: 'password',
    driverClassName: 'com.mysql.cj.jdbc.Driver'
});

var params = [
    { value: 1, isOut: false },  // IN参数:状态
    { 
        name: 'count',
        value: null,
        sqlType: 4,              // INTEGER
        isOut: true,
        isOutOnly: false         // INOUT参数
    }
];

var result = conn.callProcedureFull(
    'CALL count_users_by_status(?, ?)',
    params,
    function(rs) {
        // 如果存储过程不返回结果集,函数体可以为空
    }
);

console.log('用户数量:', result.count);

示例2 - PostgreSQL: 多个INOUT参数

javascript
var conn = informat.jdbc.systemConnection();

var params = [
    { value: 'u001', isOut: false },     // IN参数:用户ID
    { value: 50, isOut: false },         // IN参数:增加积分数
    { 
        name: 'totalPoints',
        value: null,
        sqlType: 4,                      // INTEGER
        isOut: true,
        isOutOnly: false
    },
    { 
        name: 'message',
        value: null,
        sqlType: 12,                     // VARCHAR
        isOut: true,
        isOutOnly: false
    }
];

var result = conn.callProcedureFull(
    'CALL update_user_points(?, CAST(? AS INTEGER), ?, ?)', // 第二个IN参数未设置sqlType,此处需要显式类型转换
    params,
    null  //  没有结果集需要处理时,可以置空
);

console.log('更新后的总积分:', result.totalPoints);
console.log('返回消息:', result.message);

示例3 - 创建用户并获取返回值

javascript
var conn = informat.jdbc.systemConnection();

// 生成唯一ID
var recordId = informat.jdbc.nextRecordId();

var params = [
    { value: recordId, isOut: false },
    { value: 'zhangsan', isOut: false },
    { value: 'zhang@test.com', isOut: false },
    { value: 25, sqlType: 4, isOut: false },
    { 
        name: 'userId',
        value: null,
        sqlType: 12,    // VARCHAR
        isOut: true,
        isOutOnly: false
    },
    { 
        name: 'points',
        value: null,
        sqlType: 4,     // INTEGER
        isOut: true,
        isOutOnly: false
    },
    { 
        name: 'message',
        value: null,
        sqlType: 12,    // VARCHAR
        isOut: true,
        isOutOnly: false
    }
];

var result = conn.callProcedureFull(
    'CALL register_user(?, ?, ?, ?, ?, ?, ?)',
    params,
    null
);

console.log('注册结果:', result.message);
if (result.userId) {
    console.log('新用户ID:', result.userId);
    console.log('赠送积分:', result.points);
}

示例4 - 处理返回的结果集

javascript
var conn = informat.jdbc.systemConnection();
var users = [];

var params = [
    { value: 1, sqlType: 4, isOut: false },  // IN参数:状态
    { 
        name: 'totalCount',
        value: null,
        sqlType: 4,
        isOut: true,
        isOutOnly: false
    }
];

// 使用handler处理结果集中的每一行
var result = conn.callProcedureFull(
    'CALL get_users_with_count(?, ?)',
    params,
    function(rs) {
        // 这个函数会对每一行数据调用一次
        users.push({
            id: rs.getString('id'),
            username: rs.getString('username'),
            email: rs.getString('email'),
            age: rs.getInt('age'),
            points: rs.getInt('points')
        });
    }
);

console.log('总用户数:', result.totalCount);
console.log('查询到', users.length, '个用户:');
users.forEach(function(user, index) {
    console.log('  ' + (index + 1) + '.', user.username, 
                '- 年龄:', user.age, '- 积分:', user.points);
});

示例5 - Oracle: 使用REF CURSOR

javascript
var conn = informat.jdbc.createConnection({
    dburl: 'jdbc:oracle:thin:@localhost:1521/XE',
    dbuser: 'user',
    dbpassword: 'password',
    driverClassName: 'oracle.jdbc.driver.OracleDriver'
});

var employees = [];

var params = [
    { value: 'IT', isOut: false },       // IN参数:部门
    { 
        name: 'cursor',
        sqlType: 2012,                   // REF_CURSOR
        isOut: true,
        isOutOnly: true                  // Oracle支持纯OUT
    }
];

conn.callProcedureFull(
    '{CALL get_employees_by_dept(?, ?)}',
    params,
    function(rs) {
        // 游标数据会自动在handler中处理
        employees.push({
            empId: rs.getString('emp_id'),
            empName: rs.getString('emp_name'),
            salary: rs.getDouble('salary')
        });
    }
);

console.log('员工列表:', employees);

示例6 - 获取统计信息(多个OUT参数)

javascript
var conn = informat.jdbc.systemConnection();

var params = [
    { value: 1, sqlType: 4, isOut: false },          // IN参数:状态
    { 
        name: 'totalCount',
        value: null,
        sqlType: 4,                      // INTEGER
        isOut: true,
        isOutOnly: false
    },
    { 
        name: 'avgSalary',
        value: null,
        sqlType: 8,                      // DOUBLE
        isOut: true,
        isOutOnly: false
    },
    { 
        name: 'totalPoints',
        value: null,
        sqlType: 4,                      // INTEGER
        isOut: true,
        isOutOnly: false
    }
];

var result = conn.callProcedureFull(
    'CALL get_user_statistics(?, ?, ?, ?)',
    params,
    null
);

console.log('统计信息:');
console.log('  总用户数:', result.totalCount);
console.log('  平均工资:', result.avgSalary);
console.log('  总积分:', result.totalPoints);

示例7 - 使用索引获取结果集字段

javascript
var conn = informat.jdbc.systemConnection();
var data = [];

var params = [
    { value: 1, sqlType: 4, isOut: false }
];

conn.callProcedureFull(
    'CALL get_users(?)',
    params,
    function(rs) {
        // 可以使用索引(从1开始)或字段名
        data.push({
            id: rs.getString(1),           // 第1列
            username: rs.getString(2),     // 第2列
            email: rs.getString(3),        // 第3列
            age: rs.getInt(4)              // 第4列
        });
    }
);

console.log('获取数据:', data.length, '条');

示例8 - 处理多个结果集

javascript
var conn = informat.jdbc.createConnection({
    dburl: 'jdbc:mysql://localhost:3306/mydb',
    dbuser: 'root',
    dbpassword: 'password',
    driverClassName: 'com.mysql.cj.jdbc.Driver'
});
var topUsers = [];
var statsInfo = null;

var params = [
    { value: 1, sqlType: 4, isOut: false }
];

conn.callProcedureFull(
    'CALL get_user_summary(?)',
    params,
    function(rs) {
        // handler会自动处理多个结果集
        // 可以通过列数判断当前是哪个结果集
        var colCount = rs.getColumnCount();
        
        if (colCount === 3) {
            // 第一个结果集: id, username, points
            topUsers.push({
                id: rs.getString('id'),
                username: rs.getString('username'),
                points: rs.getInt('points')
            });
        } else if (colCount === 5) {
            // 第二个结果集: 统计信息
            statsInfo = {
                totalCount: rs.getInt('total_count'),
                avgSalary: rs.getDouble('avg_salary'),
                totalPoints: rs.getInt('total_points'),
                maxAge: rs.getInt('max_age'),
                minAge: rs.getInt('min_age')
            };
        }
    }
);

console.log('Top用户(前5名):', topUsers.length, '人');
topUsers.forEach(function(user, idx) {
    console.log('  ' + (idx + 1) + '.', user.username, '- 积分:', user.points);
});

if (statsInfo) {
    console.log('统计信息:');
    console.log('  总数:', statsInfo.totalCount);
    console.log('  平均工资:', statsInfo.avgSalary);
    console.log('  总积分:', statsInfo.totalPoints);
    console.log('  年龄范围:', statsInfo.minAge, '-', statsInfo.maxAge);
}

示例9 - SQL Server: 带返回值和OUT参数

javascript
var conn = informat.jdbc.createConnection({
    dburl: 'jdbc:sqlserver://localhost:1433;databaseName=mydb',
    dbuser: 'sa',
    dbpassword: 'password',
    driverClassName: 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
});

var params = [
    { 
        name: 'returnValue',
        value: null,
        sqlType: 4,                      // INTEGER (RETURN值)
        isOut: true,
        isOutOnly: true
    },
    { value: 'zhangsan', isOut: false }, // IN参数:用户名
    { value: 'password123', isOut: false }, // IN参数:密码
    { 
        name: 'userId',
        value: null,
        sqlType: 12,                     // VARCHAR
        isOut: true,
        isOutOnly: true
    },
    { 
        name: 'roleId',
        value: null,
        sqlType: 4,                      // INTEGER
        isOut: true,
        isOutOnly: true
    }
];

// SQL Server: 使用 {? = CALL ...} 语法获取RETURN值
var result = conn.callProcedureFull(
    '{? = CALL sp_user_login(?, ?, ?, ?)}',
    params,
    function(rs) {
        // 如果存储过程返回结果集,在这里处理
    }
);

console.log('返回值:', result.returnValue);  // 0=成功, -1=失败
console.log('用户ID:', result.userId);
console.log('角色ID:', result.roleId);

if (result.returnValue === 0) {
    console.log('登录成功');
} else {
    console.log('登录失败');
}

数据库差异说明

参数类型支持:

  • PostgreSQL: 只支持INOUT参数,不支持纯OUT参数,isOutOnly应设为false。支持通过游标(sqlType: 1111)返回结果集
  • MySQL: 支持IN、OUT、INOUT三种参数类型。支持返回多个结果集
  • Oracle: 支持IN、OUT、INOUT,通过REF_CURSOR(sqlType: 2012)返回结果集
  • SQL Server: 支持IN、OUT、INOUT,并有RETURN返回值(需作为第一个参数)

SQL语法差异:

  • PostgreSQL: CALL procedure_name(?, ?)
  • MySQL: CALL procedure_name(?, ?)
  • Oracle: {CALL procedure_name(?, ?)}
  • SQL Server: {CALL procedure_name(?, ?)}{? = CALL procedure_name(?, ?)}

类型转换:

  • PostgreSQL: 如果在params中指定了sqlType,则无需在SQL中使用CAST(? AS 类型),系统会自动处理类型转换
  • 其他数据库: 建议在params中指定sqlType,可以避免类型转换问题

注意事项

  1. handler参数必填: 即使存储过程不返回结果集,也必须提供handler函数
  2. OUT/INOUT参数必须设置sqlType: 类型值参考上方"SQL类型常量表"
  3. 参数命名: 为OUT/INOUT参数设置name属性,便于获取返回值
  4. NULL值处理: INOUT参数的初始值可以为null,需要在JavaScript中妥善处理返回的null值
  5. 多结果集处理: handler函数会按顺序处理所有结果集,可以通过rs.getColumnCount()或列名判断当前结果集
  6. 游标处理: PostgreSQL和Oracle的游标会在handler中自动展开为逐行数据
  7. 类型指定优势: 在params中指定sqlType可以简化SQL语句,避免手动类型转换

tableConnection

获取应用数据表的数据库连接

javascript
informat.jdbc.tableConnection()

INFO

  • 使用应用数据表的数据库连接可以查询、更新、删除应用的数据表。
  • 如果连接创建不成功会抛出异常。
  • 在使用数据表连接执行查询的时候,需要将数据表的标识符转换为小写形式

返回值

返回数据库连接对象Connection,使用此对象可进行数据库里的数据表进行添查删改操作。

示例

例如有数据表tableDemo

字段标识符名称
idID
name名称
maxAge最大年龄

需要使用以下SQL执行查询

sql
select id, name, max_age from table_demo;
javascript
var ret = []
var conn = informat.jdbc.tableConnection();
conn.select(`select id,name,create_time from task limit 10`, (rs) => {
  ret.push({
    id: rs.getString('id'),
    name: rs.getString('name'),
    createTime: rs.getTimestamp('create_time'),
  })
});
console.log('ret', ret);

如果想查询关联列表字段对应的邻接表,查询的格式为:

数据表标识符$字段标识符(驼峰转为下划线)

示例

javascript
var ret = []
var conn = informat.jdbc.tableConnection();
var sql = `select a.id from task$report a 
		inner join task b on a.id=b.id`;
conn.select(sql, (rs) => {
    ret.push(rs.getString('id'))
})
console.log('ret', ret);

systemConnection

获取系统数据库连接

javascript
informat.jdbc.systemConnection()

TIP

  • 连接创建不成功会抛出异常,使用系统数据库连接可以查询、更新、删除系统内的所有表。
  • 使用系统数据库连接可以查询、更新、删除系统内的所有数据表。需要注意的是除非是非常必要的情况下,不要使用此功能。织信内部的数据表会随着版本的迭代发生变化,直接访问系统底层数据表有可能会导致在织信版本更新后应用功能异常。
  • 需要注意的是当使用systemConnection执行SQL语句时,表名的中appid要使用informat.app.appId()获取。在应用分发的过程中appid会发生变化。

返回值

返回数据库连接对象Connection

示例

javascript
var conn = informat.jdbc.systemConnection();
var ret = []
conn.select(`select id,name,create_time from v_croe0zft168y3_task limit 10`, (rs) => {
    ret.push({
        id: rs.getString('id'),
        name: rs.getString('name'),
        createTime: rs.getTimestamp('create_time'),
    })
})
console.log('ret', ret);

nextRecordId

为记录生成唯一ID

javascript
informat.jdbc.nextRecordId();

返回值 类型String,返回13位小写字母和数字组成的字符串,并且首字母为小写字母。

示例

javascript
informat.jdbc.nextRecordId();
text
u5wxh9kl3mxvi

safesql

生成安全的sql,为带有占位符?sql生成安全的完整sql

javascript
informat.jdbc.safesql(sql, params);
参数类型描述
sqlString数据库语句
params...Object入参

返回值 类型为String,安全Sql

示例

javascript
const sql = `update tab set age=?,name=? where id=?`;
const params = [18, "李四", `'张' or 1=1`];
const result = informat.jdbc.safesql(sql, params);
sql
update
  tab
set age  = 18,
    name = '李四'
where id = ''
  '张'
  ' or 1=1'

ResultSet

TIP

columnIndex为索引时,起始索引为1

方法返回值描述
getString(columnIndex)String按照索引或者列名获取String类型的列
getBoolean(columnIndex)String按照索引或者列名获取Boolean类型的列
getByte(columnIndex)String按照索引或者列名获取Byte类型的列
getShort(columnIndex)String按照索引或者列名获取Short类型的列
getInt(columnIndex)String按照索引或者列名获取Integer类型的列
getLong(columnIndex)String按照索引或者列名获取Long类型的列
getFloat(columnIndex)String按照索引或者列名获取Float类型的列
getDouble(columnIndex)String按照索引或者列名获取Double类型的列
getBytes(columnIndex)String按照索引或者列名获取byte[]类型的列
getDate(columnIndex)String按照索引或者列名获取Date类型的列
getTime(columnIndex)String按照索引或者列名获取Time类型的列
getTimestamp(columnIndex)String按照索引或者列名获取Timestamp类型的列
getObject(columnIndex)String按照索引或者列名获取Object类型的列
getBigDecimal(columnIndex)String按照索引或者列名获取BigDecimal类型的列
getColumnCount()Integer返回结果集的列数量
getColumnName(columnIndex)String按照索引返回列名
getColumnTypeName(columnIndex)String按照索引返回列类型