Java 在存储的CLOB中包含自动增量值

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

我将一个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_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生成clob内容,然后使用ID和clob插入
  • 使用修改clob的触发器
  • 我已经写了两个关于如何做到这一点的小例子

    我个人认为,在大多数情况下,第一种方法更可取,使用触发器的解决方案可能非常脆弱,而且很难正确执行。如果clob内容(例如)是从对象模型生成的XML或JSON,那么这可能会特别棘手,在我的示例中,放置像
    ##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);
            }
        }
    }