简体   繁体   English

无法使用 PreparedStatement 从 JDBC 中的插入检索 ID

[英]Can't retrieve ID from an insert in JDBC with PreparedStatement

I'm trying to get the ID of an insert row which is auto_increment in MySQL.我正在尝试获取在 MySQL 中为auto_increment的插入行的ID I'm using the parameter Statement.RETURN_GENERATED_KEYS in the prepareStatement method and trying to obtain it via the getGeneratedKeys method.我在prepareStatement方法中使用参数Statement.RETURN_GENERATED_KEYS并尝试通过getGeneratedKeys方法获取它。 Somehow, it is not retrieving the ID .不知何故,它没有检索ID

It should be noted that the insertion is done, but since the ID is not obtained, I cannot perform the other inserts and that is why it gives me the error "MySQL ERROR 1452" , because an insert is being made later with the ID 0 that does not exist.应该注意的是,插入已完成,但由于未获得ID ,我无法执行其他插入,这就是为什么它给我错误"MySQL ERROR 1452" ,因为稍后将使用ID 0进行插入那不存在。

public int insertar(Compra objC, ArrayList<DetalleCompra> listaDetalle) {
    try {
        conexion = MySQLConexion.conexion();
        
        conexion.setAutoCommit(false);
        
        procedimientoAlmacenado = conexion.prepareStatement("{call insertar_compra (?, ?)}", Statement.RETURN_GENERATED_KEYS);
        
        fecha = FORMATO_FECHA.parse(objC.getFecha());
        fechaSQL = new java.sql.Date(fecha.getTime());
        
        procedimientoAlmacenado.setDate(1, fechaSQL);
        procedimientoAlmacenado.setInt(2, objC.getIdCliente());
        
        resultado = procedimientoAlmacenado.executeUpdate();
        
        int idCompra = 0;
        
        ResultSet idGenerada = procedimientoAlmacenado.getGeneratedKeys();
            
        if (idGenerada.next()) {
            idCompra = idGenerada.getInt(1);
        }
        
        if (resultado != 0) {
            for (DetalleCompra x : listaDetalle) {
                procedimientoAlmacenado = conexion.prepareCall("{call insertar_detalle_compra (?, ?, ?)}");
                
                procedimientoAlmacenado.setInt(1, idCompra);
                procedimientoAlmacenado.setInt(2, x.getIdProducto());
                procedimientoAlmacenado.setInt(3, x.getCantidad());
                
                resultado = procedimientoAlmacenado.executeUpdate();
                
                procedimientoAlmacenado = conexion.prepareCall("{disminuir_stock (?, ?)}");
                
                procedimientoAlmacenado.setInt(1, x.getIdProducto());
                procedimientoAlmacenado.setInt(2, x.getCantidad());
                
                resultado = procedimientoAlmacenado.executeUpdate();
            }
        }
        
        conexion.commit();
    } catch (Exception e) {
        System.out.println(e.getMessage());
        
        try {
            conexion.rollback();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
    } finally {
        try {
            if (procedimientoAlmacenado != null)
                procedimientoAlmacenado.close();
            
            if (conexion != null)
                conexion.close();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
    
    return resultado;
}

I also tried to create a variable:我还尝试创建一个变量:

String[] generatedId = { "ID" };

and place it in the method prepareStatement :并将其放在方法prepareStatement中:

procedimientoAlmacenado = conexion.prepareStatement("{call insertar_compra (?, ?)}", generatedId);

However, it doesn't work either.但是,它也不起作用。 I'm suspecting that it has to do with the fact that I'm doing the statement inside a stored procedure, or with setAutoCommit(false) , but I can't think of anything else.我怀疑这与我在存储过程中或与setAutoCommit(false)执行语句有关,但我想不出其他任何事情。

Ok so what I did was make the stored procedure return me the last inserted ID:好的,我所做的就是让存储过程返回最后插入的 ID:

delimiter $$
create procedure insertar_compra (in fec datetime, in client_id int, out id int)
begin
    insert into compra values (null, fec, client_id, 'P');
    
    set id = LAST_INSERT_ID();
end; $$
delimiter ;

And then I got it with the registerOutParameter() method:然后我用registerOutParameter()方法得到了它:

public int insertar(Compra objC, ArrayList<DetalleCompra> listaDetalle) {
        try {
            conexion = MySQLConexion.conexion();
            
            conexion.setAutoCommit(false);
            
            procedimientoAlmacenado = conexion.prepareCall("{call insertar_compra (?, ?, ?)}");
            
            fecha = FORMATO_FECHA.parse(objC.getFecha());
            
            fechaSQL = new Timestamp(fecha.getTime());
            
            procedimientoAlmacenado.setTimestamp(1, fechaSQL);
            procedimientoAlmacenado.setInt(2, objC.getIdCliente());
            procedimientoAlmacenado.registerOutParameter(3, Types.INTEGER);
            
            resultado = procedimientoAlmacenado.executeUpdate();
            
            int idCompra = 0;
            
            idCompra = procedimientoAlmacenado.getInt(3);
            
            if (resultado != 0) {
                for (DetalleCompra x : listaDetalle) {
                    procedimientoAlmacenado = conexion.prepareCall("{call insertar_detalle_compra (?, ?, ?)}");
                    
                    procedimientoAlmacenado.setInt(1, idCompra);
                    procedimientoAlmacenado.setInt(2, x.getIdProducto());
                    procedimientoAlmacenado.setInt(3, x.getCantidad());
                    
                    resultado = procedimientoAlmacenado.executeUpdate();
                    
                    procedimientoAlmacenado = conexion.prepareCall("{call disminuir_stock (?, ?)}");

                    procedimientoAlmacenado.setInt(1, x.getIdProducto());
                    procedimientoAlmacenado.setInt(2, x.getCantidad());
                    
                    resultado = procedimientoAlmacenado.executeUpdate();
                }
            }
            
            conexion.commit();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            
            try {
                conexion.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if (procedimientoAlmacenado != null)
                    procedimientoAlmacenado.close();
                
                if (conexion != null)
                    conexion.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        
        return resultado;
    }

Thanks to Mark Rotteveel for the suggestion!感谢Mark Rotteveel的建议!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM