【问题标题】:Spring JdbcTemplate Cannot Get Insert ID from MySQLSpring JdbcTemplate 无法从 MySQL 获取插入 ID
【发布时间】:2012-03-10 04:30:30
【问题描述】:

我正在尝试在 MySQL 表中插入一行并获取它的插入 ID。我知道 MySQL last_insert_id() 函数,但我似乎无法让它工作。目前,我正在尝试使用一个注释为事务的函数,但我只返回 0。我正在使用 Spring 3.1。

    @Transactional (propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    private long insertTransactionRecord 
    (
        int custID, 
        int porID, 
        String date, 
        short crvID
    ) {
        m_template.update ("INSERT INTO " +
                           "    transaction " +
                           "( " +
                           "    por_id, " +
                           "    cust_id, " +
                           "    trans_date, " +
                           "    crv_id " +
                           ") " +
                           "VALUES " +
                           "( " +
                           "    ?, " +
                           "    ?, " +
                           "    ?, " +
                           "    ? " +
                           ")",
                           new Object[] {
                               porID,
                               custID,
                               date,
                               crvID
                           });
        return m_template.queryForLong ("SELECT " +
                                        "    last_insert_id() " +
                                        "FROM " +
                                        "    transaction " +
                                        "LIMIT 1");
    }

【问题讨论】:

    标签: java mysql sql spring


    【解决方案1】:

    使用 Spring 的内置支持而不是自己做。

    SqlUpdate insert = new SqlUpdate(ds, "INSERT INTO company (name) VALUES (?)");
    insert.declareParameter(new SqlParameter(Types.VARCHAR)); 
    insert.setReturnGeneratedKeys(true);
    // assuming auto-generated col is named 'id'
    insert.setGeneratedKeysColumnNames(new String[] {"id"}); 
    insert.compile();
    ....
    GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
    insert.update(new Object[]{"test"}, keyHolder);
    System.out.println(keyHolder.getKey().longValue());
    

    【讨论】:

    【解决方案2】:

    The documentation 揭示了获取最后一个插入 ID 的语法是:

    SELECT LAST_INSERT_ID()    
    

    【讨论】:

    • 我明白这一点。它在JdbcTemplate 中不起作用。如果我在 MySQL 客户端中手动运行它,它就可以工作。
    • 如果你明白这一点,你为什么要使用SELECT last_insert_id() FROM transaction LIMIT 1
    • 因为JdbcTemplate 使用连接池,所以我不能保证我会从正确的表中获取ID。在 MySQL 客户端中包含 FROM 子句。有一些博客文章建议了这种做法。
    • Spring 不可能为在同一个数据库事务中执行的两条语句使用两个不同的 JDBC 连接。如果是这样,那么就没有什么是交易性的了。使用文档告诉您使用的内容。并阅读它以了解它的作用。
    • 另外,当我把FROM 拿出来时,它并不能解决任何问题。
    【解决方案3】:

    取自这里http://www.codefutures.com/spring-dao/

    public int createCompany(Company company) throws SQLException {
            jdbcTemplate.update(
                    "INSERT INTO company (name) VALUES (?)",
                    company.getName()
            );
            return jdbcTemplate.queryForInt( "select last_insert_id()" );
        }
    

    如果你注意到那里没有FROM

    【讨论】:

    • FROM 子句的目的是指定我想要从中获取 ID 的表。 JdbcTemplate 使用连接池,所以我不能保证在同一个连接上。该交易本应解决这一问题。您的建议没有帮助,不过谢谢。
    • 使用 jdbcTemplate.queryForObject("select last_insert_id()", Integer.class)
    • 我不认为这种方法是线程安全的,是吗? queryForInt(..) 调用可能在多次插入发生后发生,并为上面的插入语句返回错误的 ID。
    • @MarkRoper - 据我了解,一旦正确配置 JDBC,它就是线程安全的,根据我的经验,它是开箱即用的正确配置。在这里阅读:docs.spring.io/spring/docs/current/spring-framework-reference/…
    猜你喜欢
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    相关资源
    最近更新 更多