繁体   English   中英

使用准备好的语句返回时间戳

[英]Return Timestamp With Prepared Statement

我有一个自动生成的时间戳,每次在mysql表中插入或更新一条记录时都会创建该时间戳。 有没有一种方法可以类似于使用密钥持有者返回新创建的id的方式返回此时间戳?

KeyHolder keyHolder = new GeneratedKeyHolder();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

//Insert Contact
jdbcTemplate.update(new PreparedStatementCreator() {
    @Override
    public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
        PreparedStatement preparedStatement = connection.prepareStatement(SQL_ADD, Statement.RETURN_GENERATED_KEYS);
        preparedStatement.setString(1, contact.getFirstName());
        preparedStatement.setString(2, contact.getLastName());
        preparedStatement.setInt(3, contact.getOrganizationId());
        preparedStatement.setString(4, contact.getType());
        preparedStatement.setInt(5, contact.getUserId());
        return preparedStatement;
        }   
}, keyHolder);
//Use keyholder to obtain newly created id
contact.setId(keyHolder.getKey().intValue());

是否有某种方法也可以返回新的时间戳而不必重新查询表? 我一直在寻找将ID与ID一起作为密钥返回给密钥持有者的方法,但是它似乎没有作为密钥返回吗?

不太令人满意,但我认为“否”是您问题的答案。 我不了解Spring的任何内容,但是我认为这是由于包装了基本的JDBC。 请参阅http://docs.oracle.com/javase/6/docs/api/java/sql/Statement.html#getGeneratedKeys%28%29

您唯一的选择是在MySQL上创建一个具有out参数的存储过程,然后调用该存储过程。 参见http://dev.mysql.com/doc/refman/5.0/en/call.html

似乎变量contact是新插入记录的实例。 由于它包含新生成的id (主键)字段值,因此您可以执行新查询以返回此新id所需的timestamp字段值。

该查询可能看起来像这样:

select timestamp_field from my_table where id=?

使用PreparedStatement输入新的id值并执行以获取所需的timestamp字段值。

GeneratedKeyHolder还具有两个方法: getKeyList()返回所生成字段的Map<String,Object> getKeyList() ,为所有受影响的行生成一个生成键的列表。

参见GeneratedKeyHolder的 Java文档和自动生成键的Spring教程

另外,Spring的SimpleJdbcInsert具有生成密钥检索的方法。 另请参见方法SimpleJdbcInsert#usingGeneratedKeyColumns

java.sql.Connection类中有2种方法,导致PreparedStatement执行返回选择的键列:

PreparedStatement prepareStatement(String sql,
                                   int[] columnIndexes)
                                throws SQLException

PreparedStatement prepareStatement(String sql,
                                   String[] columnNames)
                                   throws SQLException

您不需要使用Spring KeyHolder和JDBCTemplate来执行此操作。
给您希望可以编号/命名您的时间戳列。 但是javadoc不需要或建议任何JDBC实现都可以返回非键列,因此使用这种方法很不走运:

创建一个默认的PreparedStatement对象,该对象能够返回由给定数组指定的自动生成的键。 此数组包含目标表中包含应返回的自动生成键的列的名称。


  • 正如另一个答案中所建议的那样,可以切换到完全符合您想要的功能的存储过程(CallableStatement实际上是一个执行存储过程的PreparedStatement-即子类)。

  • 可以通过new Timestamp(new Date())填充预准备语句中的timestamp列-但您应该具有一种机制来在各个服务器之间同步时间(通常在Windows和* nix环境中使用)。 仅当尚未提供值时,触发器才可以设置时间戳。

作为应用程序和数据库设计的一部分,您需要致力于某些操作发生的地方的哲学。 如果数据库派生了所需的数据,则应用程序需要刷新数据-您必须支付单独的查询执行或插入和检索的组合存储过程的代价。

在MySQL数据库服务器端,解决此问题的方法很少。 您可以从在表上创建TRIGGER开始。 由于TRIGGER有限制并且不能返回数据,因此可以将TIMESTAMP值设置为变量:

DEMILITER //
CREATE TRIGGER ai_tbl_name AFTER INSERT ON tbl_name
FOR EACH ROW
BEGIN

SET @TimeStamp = NEW.timestamp_column;

END;//
DELIMITER ;

要获取此时间戳记值,请运行以下命令:

SELECT @TimeStamp;

由于变量存储在内存中,因此无需再次打开任何表。

您走得更远。 您可以在MySQL中创建一个STORED PROCEDURE来自动执行上述所有操作(示例代码,因为我不知道您表的详细信息):

DELIMITER //
DROP PROCEDURE IF EXISTS sp_procedure_name //
CREATE PROCEDURE sp_procedure_name (IN col1_val VARCHAR(25),
                                    IN col2_val VARCHAR(25),
                                    IN col3_val INT)
BEGIN
    INSERT INTO tbl_name (col1, col2, col3)
    VALUES (col1_val, col2_val, col3_val);

    SELECT @TimeStamp;
END; //
DELIMITER ;

您可以使用以下代码运行此过程:

CALL sp_procedure_name(col1_val, col2_val, col3_val);

由于我不熟悉Java,因此您需要在代码方面完成它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM