簡體   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