Java 在存储的CLOB中包含自动增量值
我将一个json对象作为clob存储在一个表中,该表有一个自动增量ID字段。我想在存储时在clob中包含自动增量ID。有没有办法做到这一点,而不需要在插入后再次更新记录。(我将jdbc与h2引擎一起使用)以下是一个解决方案: (1)使用序列:Java 在存储的CLOB中包含自动增量值,java,sql,jdbc,h2,Java,Sql,Jdbc,H2,我将一个json对象作为clob存储在一个表中,该表有一个自动增量ID字段。我想在存储时在clob中包含自动增量ID。有没有办法做到这一点,而不需要在插入后再次更新记录。(我将jdbc与h2引擎一起使用)以下是一个解决方案: (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_s
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)顺序的替代应用:
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;
使用以下脚本运行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
使用此序列值插入目标表的多列。基本上有两种解决方案:
##ID##
这样的占位符并不总是可行的或很难做到(例如,如果字段类型为整数)
1.使用序列
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);
}
}
}
您是指增量id值-存储在id列中?而且,clob中的json需要添加这个递增字段?您是否考虑过使用应用程序生成的自动增量ID来实现此目的?另一种方法是使用两个表—一个带有自动增量ID列的主表。还有一个带有clob(带有json数据)列的辅助表。在一个事务中可能需要执行插入两个表。我想这也行。我想将递增ID列的值存储到CLOB。除非读取表中的最后一个ID,否则无法获取应用程序生成的ID(递增的),对吗?这将是2个事务。拥有2个表将增加复杂性,同时还有2个事务。我正在寻找最简单的方法来实现这一点。\u除非我读取表中的最后一个ID,否则我无法获取应用程序生成的ID(递增的)?\u嗯,您可以有一个
应用程序\u d
表,其中有一列跟踪ID号。虽然解决方案1a是一个起点,但这并不能真正解决问题。谢谢。这为解决方案提供了一个基础好的建议,但这个问题给我的印象是一个(或者可能只是一个“为什么?”的问题)。如果重点是将CLOB与自动增量ID关联,那么这是将(原始)CLOB插入表的自然结果。实际上不需要修改CLOB本身,因为CLOB和ID都“链接”在数据库表的同一行中。如果在某个时候CLOB需要更新以包含ID,那么在提取它时,而不是在插入它时,可能会发生这种情况。@GordThompson这可能确实是一个XY问题。我只是喜欢以这个问题为出发点进行实验;)也就是说,我可以想到clob可以包含包括id在内的记录的序列化表示的情况(例如,可能是为了加快某些RESTAPI的速度,以避免它必须在每个请求上构建和序列化相同的消息)。在这种情况下,解决方案2中的触发器可能会完成创建clob的所有工作(对于更新触发器来说也很有用,以保持clob的最新状态)。@MarkRotterVeel这回答了问题。谢谢
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);
}
}
}