我将json对象作为clob存储在表中,该表具有自动增量ID字段。我想在存储时在Clob中包含自动增量ID。有没有办法做到这一点,插入后再不更新记录。 (我在h2引擎上使用了jdbc)
答案 0 :(得分:1)
基本上有两种解决方案:
我已经写了两个小例子来说明如何做到这一点。
我个人认为,在大多数情况下,使用第一个触发器更为可取,使用触发器的解决方案可能非常脆弱且难以正确执行。如果Clob内容是-例如-从对象模型生成的XML或JSON,在我的示例中放置##ID##
之类的占位符并不总是可行或很难做到的(例如,如果字段是输入整数)。
public class WithSequence {
private static final String URL = "jdbc:h2:mem:seqdb";
public static void main(String[] args) throws SQLException {
try (Connection connection = DriverManager.getConnection(URL)) {
initDb(connection);
int id = getNextId(connection);
insertClobWithId(id, connection);
outputTableContent(connection);
}
}
// creates table and sequence
private static void initDb(Connection connection) throws SQLException {
try (Statement ddlStmt = connection.createStatement()) {
ddlStmt.execute("create table clobwithid ("
+ " id integer primary key,"
+ " clobvalue clob"
+ ")");
ddlStmt.execute("create sequence seq_clobwithid");
}
}
// obtain next id from sequence
private static int getNextId(Connection connection) throws SQLException {
try (Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select next value for seq_clobwithid")) {
if (rs.next()) {
return rs.getInt(1);
} else {
throw new AssertionError(" next value for should produce value");
}
}
}
// generate and insert clob
private static void insertClobWithId(int id, Connection connection) throws SQLException {
String clobValue = "Something with id=" + id + " and other stuff";
try (PreparedStatement pstmt = connection.prepareStatement(
"insert into clobwithid(id, clobvalue) values(?, ?)")) {
pstmt.setInt(1, id);
pstmt.setString(2, clobValue);
pstmt.executeUpdate();
}
}
private static void outputTableContent(Connection connection) throws SQLException {
try (Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select id, clobvalue from clobwithid")) {
while (rs.next()) {
System.out.printf("%d : %s%n", rs.getInt(1), rs.getString(2));
}
}
}
}
public class WithTrigger {
private static final String URL = "jdbc:h2:mem:seqdb";
public static void main(String[] args) throws SQLException {
try (Connection connection = DriverManager.getConnection(URL)) {
initDb(connection);
insertClob(connection);
outputTableContent(connection);
}
}
// create database and trigger
private static void initDb(Connection connection) throws SQLException {
try (Statement ddlStmt = connection.createStatement()) {
ddlStmt.execute("create table clobwithid ("
+ " id integer auto_increment primary key,"
+ " clobvalue clob"
+ ")");
ddlStmt.execute("create trigger bi_clobwithid before insert on clobwithid for each row call \"example.ClobUpdateTrigger\"");
}
}
// insert clob with a placeholder to be modified by the trigger
private static void insertClob(Connection connection) throws SQLException {
String clobValue = "Something with id=##ID## and other stuff";
try (PreparedStatement pstmt = connection.prepareStatement(
"insert into clobwithid(clobvalue) values(?)")) {
pstmt.setString(1, clobValue);
pstmt.executeUpdate();
}
}
private static void outputTableContent(Connection connection) throws SQLException {
try (Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select id, clobvalue from clobwithid")) {
while (rs.next()) {
System.out.printf("%d : %s%n", rs.getInt(1), rs.getString(2));
}
}
}
}
触发器类别为:
public class ClobUpdateTrigger extends TriggerAdapter {
@Override
public void fire(Connection connection, ResultSet oldRs, ResultSet newRs) throws SQLException {
int generatedId = newRs.getInt(1);
// We need to use reader to avoid internal casting problems
String insertedClobValue = toString(newRs.getCharacterStream("clobvalue"));
String updatedClobValue = insertedClobValue != null
? insertedClobValue.replace("##ID##", String.valueOf(generatedId))
: null;
newRs.updateString("clobvalue", updatedClobValue);
}
private static String toString(Reader reader) throws SQLException {
try {
StringWriter sw = new StringWriter();
char[] buffer = new char[1024];
int read;
while ((read = reader.read(buffer)) != -1) {
sw.write(buffer, 0, read);
}
return sw.toString();
} catch (IOException e) {
throw new SQLException(e);
}
}
}
答案 1 :(得分:0)
这是一个解决方案:
(1)使用序列:
CREATE TABLE test1 (my_id INT PRIMARY KEY, my_id_2 INT);
CREATE SEQUENCE my_seq;
INSERT INTO test1 VALUES (my_seq.nextval, my_seq.currval)
SELECT * FROM test1;
输出:
MY_ID MY_ID_2
1 1
请注意,这两列具有相同的生成值。
(1a)序列的替代应用:
使用以下脚本使用语句运行SQL:“为my_seq调用下一个值”以获取下一个序列值。
ResultSet rs = statement.executeQuery("call next value for my_seq");
rs.next();
long value = rs.getLong(1); // NOTE: the return value is a long
使用此序列值插入目标表的多个列中。