Spring JdbcTemplate无法从MySQL中获取插入ID

6

我试图向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");
    }
3个回答

9

使用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());

3
Spring在手册中也有一个例子:http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/jdbc.html#jdbc-auto-genereted-keys - Christian

8
引用自这里: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 使用连接池,因此不能保证使用同一连接。事务本应解决这个问题,但你提出的建议并没有起到帮助作用,还是谢谢了。 - Nik
使用jdbcTemplate.queryForObject("select last_insert_id()", Integer.class)。 - singhspk
3
我不认为这种方法是线程安全的,对吗?如果在多次插入操作之后调用queryForInt(..),它可能会返回上面插入语句的错误ID。 - Mark Roper
@MarkRoper - 据我所知,一旦JDBC正确配置,它就是线程安全的,并且根据我的经验,它已经默认正确配置。在这里阅读:https://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html#jdbc-JdbcTemplate-idioms - ShayLivyatan

1

文档显示获取最后插入ID的语法为:

SELECT LAST_INSERT_ID()    

我明白了。在JdbcTemplate中它不起作用。如果我在MySQL客户端手动运行它,它就可以工作。 - Nik
1
如果你已经理解了这个,为什么还要使用 SELECT last_insert_id() FROM transaction LIMIT 1 - JB Nizet
1
因为JdbcTemplate使用连接池,所以我无法保证我能从正确的表中获取ID。在MySQL客户端中包含FROM子句是可行的。有博客文章建议这种做法。 - Nik
1
Spring 没有办法在同一个数据库事务中使用两个不同的 JDBC 连接来执行两个语句。如果这样做,就没有什么可以进行事务控制了。使用文档中告诉你要使用的内容,并阅读它以了解其功能。 - JB Nizet
另外,当我删除FROM时,它并没有解决问题。 - Nik
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接