mysql数据库插入记录时怎么得到刚插入记录的ID

时间:2022-10-17 21:46:59
如题,我写了这样的不行,得到的ID是0:
public long saveAndReturnID(String strSQL){
        long retID = 0;
        Statement stmt = null;
        ResultSet rs = null;
        try{
           
  stmt = conn.createStatement();
  stmt.executeUpdate(strSQL);

  org.gjt.mm.mysql.Statement myst = (org.gjt.mm.mysql.Statement) stmt;
  retID = myst.getLastInsertID();

   myst.close();
            stmt.close();
        }catch(Throwable e) {
            e.printStackTrace();
        }finally{
            try{
                if (null != stmt)
                    stmt.close();
            }catch (Throwable e){
                e.printStackTrace();
            }
        }
        return retID;
    }

23 个解决方案

#1



SELECT LAST_INSERT_ID();

#2


没用过!帮顶!

#3


1楼说的有道理,楼主可以试一下。

#4


LAST_INSERT_ID是常量吗?

#5


引用 4 楼 sforiz 的回复:
LAST_INSERT_ID是常量吗?

是mysql里面的一个函数。

#6


不能这样做,这样做是不对的,比如两个人同时插入了一条数据,那你这样得到的是哪条数据的 ID 呢?

JDBC 就能完成这个功能,不需要你再强转成 MySQL JDBC 专用的类库 

stmt.executeUpdate(strSQL); 

改成

stmt.executeUpdate(strSQL, Statement.RETURN_GENERATED_KEYS);
ResultSet newid = stmt.getGeneratedKeys()l
newid.next();
int id = newid.getInt(1);

另外,MySQL 的 JDBC 驱动你应该使用 com.mysql.jdbc.Driver,那个 mm 的驱动程序已经是老掉牙的了,MySQL 为了保持兼容性而保留的。

#7


在数据库放的时候定义一个变量,将它放在变量里不就不用在从里面去了吗,直接用

#8


引用 6 楼 bao110908 的回复:
不能这样做,这样做是不对的,比如两个人同时插入了一条数据,那你这样得到的是哪条数据的 ID 呢?

 JDBC 就能完成这个功能,不需要你再强转成 MySQL JDBC 专用的类库

 stmt.executeUpdate(strSQL);

 改成

 stmt.executeUpdate(strSQL, Statement.RETURN_GENERATED_KEYS);
 ResultSet newid = stmt.getGeneratedKeys()l
 newid.next();
 int id = newid.getInt(1);

 另外,MySQL 的 JDBC 驱动你应该使用 com.mysql.jdbc.Driver,那个 mm 的驱动程序已经是老掉牙的了,MySQL 为了保持兼容性而保留的。


你理解错了
SELECT LAST_INSERT_ID() / SELECT @@INDENTITY 都是单个连接的,不存在所谓的两个人都同时插入,分不清的问题:
The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client. This value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions. 

唯一的问题是,如果一句INSERT插入多条,返回的是第一个ID
mysql> INSERT INTO t VALUES
    -> (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM t;
+----+------+
| id | name |
+----+------+
|  1 | Bob  |
|  2 | Mary |
|  3 | Jane |
|  4 | Lisa |
+----+------+
4 rows in set (0.01 sec)

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)

#9


同时有多个人在添加数据,所以这个方法得到的结果并不一定是你才插入的那个记录。
如果使用hibernate可以在插入记录后得到插入记录编号,这个就是你刚刚插入的了

#10


先获取表里所有记录ID的最大值,再加1

我觉得表中的ID还是由自己控制好些(不要让它自增什么的),这样好管理

#11


引用 9 楼 jeff0002 的回复:
同时有多个人在添加数据,所以这个方法得到的结果并不一定是你才插入的那个记录。
 如果使用hibernate可以在插入记录后得到插入记录编号,这个就是你刚刚插入的了

如我上面已经说过了,不存在多人添加数据找不到正确结果的问题——除非你愚蠢到整个系统用同一个连接及同一个事务。

引用 10 楼 ruoye_2008 的回复:
先获取表里所有记录ID的最大值,再加1

 我觉得表中的ID还是由自己控制好些(不要让它自增什么的),这样好管理

这样才是自取其辱之道,这样做,在多线程、高并发的环境下,既增加系统负担,同时还会造成取到的新ID重复的现象

#12


哦,是这样啊,呵呵

不过,MySQL 的 JDBC 文档还是推荐使用 JDBC 3.0 的 getGeneratedKeys() 方法,官方的说法是:使用 SELECT LAST_INSERT_ID() 方式增加了一次与数据库交互。详见: http://dev.mysql.com/doc/refman/5.1/zh/connectors.html#cj-retrieve-autoinc

这个链接中分别使用 getGenerateKeys、LAST_INSERT_ID 和可更新结果集做了示例。并在最后部分,分析了一下 getGenerateKeys() 和 LAST_INSERT_ID 的不足之处,楼主有兴趣的话可以去看一下。

#13


进来学习一下

#14


把主键设置为自增长的,就ok了

#15


mysql好久不用了,帮顶!

#16


自己建个表,实现类似oracle序列的功能。
两个字段:seqName、curVal。
尽量不使用自增长,不好控制。

#17


主键设置为自增长的

#18


引用 16 楼 yuzuru 的回复:
自己建个表,实现类似oracle序列的功能。
 两个字段:seqName、curVal。
 尽量不使用自增长,不好控制。

见我11楼回复的后半段

#19


引用 18 楼 shine333 的回复:
引用 16 楼 yuzuru 的回复:
 自己建个表,实现类似oracle序列的功能。
  两个字段:seqName、curVal。
  尽量不使用自增长,不好控制。

 见我11楼回复的后半段


见到了,但实际开发中用的不是你那套理论。

#20


学习

#21


进来学习了

#22


引用 19 楼 yuzuru 的回复:
引用 18 楼 shine333 的回复:
 引用 16 楼 yuzuru 的回复:
  自己建个表,实现类似oracle序列的功能。
   两个字段:seqName、curVal。
   尽量不使用自增长,不好控制。

  见我11楼回复的后半段


 见到了,但实际开发中用的不是你那套理论。

愿闻其详

#23



取得一个字增字段的curval,最大的用途也就是用做外键引用,一次向多个表insert数据。这种情况,最好是先把主键值查出来,把数据组织好。如果先插入一个对象,再查出刚插入的主键,然后再准备另一个对象插入,顺序有点乱,代码组织不好。
自己写太麻烦了,给你找个mysql里实现序列的方案。
http://meetrice.javaeye.com/blog/89426

#1



SELECT LAST_INSERT_ID();

#2


没用过!帮顶!

#3


1楼说的有道理,楼主可以试一下。

#4


LAST_INSERT_ID是常量吗?

#5


引用 4 楼 sforiz 的回复:
LAST_INSERT_ID是常量吗?

是mysql里面的一个函数。

#6


不能这样做,这样做是不对的,比如两个人同时插入了一条数据,那你这样得到的是哪条数据的 ID 呢?

JDBC 就能完成这个功能,不需要你再强转成 MySQL JDBC 专用的类库 

stmt.executeUpdate(strSQL); 

改成

stmt.executeUpdate(strSQL, Statement.RETURN_GENERATED_KEYS);
ResultSet newid = stmt.getGeneratedKeys()l
newid.next();
int id = newid.getInt(1);

另外,MySQL 的 JDBC 驱动你应该使用 com.mysql.jdbc.Driver,那个 mm 的驱动程序已经是老掉牙的了,MySQL 为了保持兼容性而保留的。

#7


在数据库放的时候定义一个变量,将它放在变量里不就不用在从里面去了吗,直接用

#8


引用 6 楼 bao110908 的回复:
不能这样做,这样做是不对的,比如两个人同时插入了一条数据,那你这样得到的是哪条数据的 ID 呢?

 JDBC 就能完成这个功能,不需要你再强转成 MySQL JDBC 专用的类库

 stmt.executeUpdate(strSQL);

 改成

 stmt.executeUpdate(strSQL, Statement.RETURN_GENERATED_KEYS);
 ResultSet newid = stmt.getGeneratedKeys()l
 newid.next();
 int id = newid.getInt(1);

 另外,MySQL 的 JDBC 驱动你应该使用 com.mysql.jdbc.Driver,那个 mm 的驱动程序已经是老掉牙的了,MySQL 为了保持兼容性而保留的。


你理解错了
SELECT LAST_INSERT_ID() / SELECT @@INDENTITY 都是单个连接的,不存在所谓的两个人都同时插入,分不清的问题:
The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client. This value cannot be affected by other clients, even if they generate AUTO_INCREMENT values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions. 

唯一的问题是,如果一句INSERT插入多条,返回的是第一个ID
mysql> INSERT INTO t VALUES
    -> (NULL, 'Mary'), (NULL, 'Jane'), (NULL, 'Lisa');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM t;
+----+------+
| id | name |
+----+------+
|  1 | Bob  |
|  2 | Mary |
|  3 | Jane |
|  4 | Lisa |
+----+------+
4 rows in set (0.01 sec)

mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)

#9


同时有多个人在添加数据,所以这个方法得到的结果并不一定是你才插入的那个记录。
如果使用hibernate可以在插入记录后得到插入记录编号,这个就是你刚刚插入的了

#10


先获取表里所有记录ID的最大值,再加1

我觉得表中的ID还是由自己控制好些(不要让它自增什么的),这样好管理

#11


引用 9 楼 jeff0002 的回复:
同时有多个人在添加数据,所以这个方法得到的结果并不一定是你才插入的那个记录。
 如果使用hibernate可以在插入记录后得到插入记录编号,这个就是你刚刚插入的了

如我上面已经说过了,不存在多人添加数据找不到正确结果的问题——除非你愚蠢到整个系统用同一个连接及同一个事务。

引用 10 楼 ruoye_2008 的回复:
先获取表里所有记录ID的最大值,再加1

 我觉得表中的ID还是由自己控制好些(不要让它自增什么的),这样好管理

这样才是自取其辱之道,这样做,在多线程、高并发的环境下,既增加系统负担,同时还会造成取到的新ID重复的现象

#12


哦,是这样啊,呵呵

不过,MySQL 的 JDBC 文档还是推荐使用 JDBC 3.0 的 getGeneratedKeys() 方法,官方的说法是:使用 SELECT LAST_INSERT_ID() 方式增加了一次与数据库交互。详见: http://dev.mysql.com/doc/refman/5.1/zh/connectors.html#cj-retrieve-autoinc

这个链接中分别使用 getGenerateKeys、LAST_INSERT_ID 和可更新结果集做了示例。并在最后部分,分析了一下 getGenerateKeys() 和 LAST_INSERT_ID 的不足之处,楼主有兴趣的话可以去看一下。

#13


进来学习一下

#14


把主键设置为自增长的,就ok了

#15


mysql好久不用了,帮顶!

#16


自己建个表,实现类似oracle序列的功能。
两个字段:seqName、curVal。
尽量不使用自增长,不好控制。

#17


主键设置为自增长的

#18


引用 16 楼 yuzuru 的回复:
自己建个表,实现类似oracle序列的功能。
 两个字段:seqName、curVal。
 尽量不使用自增长,不好控制。

见我11楼回复的后半段

#19


引用 18 楼 shine333 的回复:
引用 16 楼 yuzuru 的回复:
 自己建个表,实现类似oracle序列的功能。
  两个字段:seqName、curVal。
  尽量不使用自增长,不好控制。

 见我11楼回复的后半段


见到了,但实际开发中用的不是你那套理论。

#20


学习

#21


进来学习了

#22


引用 19 楼 yuzuru 的回复:
引用 18 楼 shine333 的回复:
 引用 16 楼 yuzuru 的回复:
  自己建个表,实现类似oracle序列的功能。
   两个字段:seqName、curVal。
   尽量不使用自增长,不好控制。

  见我11楼回复的后半段


 见到了,但实际开发中用的不是你那套理论。

愿闻其详

#23



取得一个字增字段的curval,最大的用途也就是用做外键引用,一次向多个表insert数据。这种情况,最好是先把主键值查出来,把数据组织好。如果先插入一个对象,再查出刚插入的主键,然后再准备另一个对象插入,顺序有点乱,代码组织不好。
自己写太麻烦了,给你找个mysql里实现序列的方案。
http://meetrice.javaeye.com/blog/89426