使用准备语句返回时间戳

时间:2012-10-28 15:07:22

标签: java mysql spring jdbc timestamp

每次在mysql表中插入或更新记录时,都会创建一个自动生成的时间戳。有没有办法以类似于使用keyholder返回新创建的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作为密钥持有者中的密钥一起返回,但它似乎不作为密钥返回?

5 个答案:

答案 0 :(得分:1)

不是很满意,但我认为“不”是你问题的答案。我不知道任何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

答案 1 :(得分:0)

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

查询可能如下所示:

select timestamp_field from my_table where id=?

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

答案 2 :(得分:0)

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

请参阅GeneratedKeyHolderSpring tutorial of auto generated keys

的java文档

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

答案 3 :(得分:0)

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

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

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

您不需要使用Spring KeyHolder&amp; JDBCTemplate这样做。
希望您可以编号/命名您的时间戳列。但是javadoc并不要求或建议任何JDBC实现都可以返回非键列,所以你对这种方法感到不快:

  

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


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

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

作为您应用的一部分&amp;数据库设计,您需要承诺某些操作发生的原则。如果数据库导出所需数据,则应用程序需要刷新数据 - 您必须支付单独查询执行的价格或插入&amp;的组合存储过程。检索。

答案 4 :(得分:0)

在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,你需要用你的代码完成它。