quinta-feira, 5 de janeiro de 2012

Recuperando código pelo auto increment no insert MySql

Ontem (04/01/2011), fiquei no trabalho até mais tarde fazendo meu projeto final de graduação em ciência da computação e, em uma determinada situação eu precisava inserir um registro no banco(MySql) e logo após inserir, precisava saber qual o código gerado pela coluna auto increment. Como o MySql não tem sequence, fica dificil saber qual foi o código gerado e eu não estava trabalhando com select max para gerar o código. Estava usando uma coluna auto increment. O esquema da tabela que tinha a coluna auto increment era esse:

CREATE TABLE TB_PREGAO(
CODIGO INTEGER PRIMARY KEY AUTO_INCREMENT,
DESCRICAO VARCHAR(255),
DATA_CRIACAO DATETIME
);

A minha codificação java para inserir um registro nessa tabela era:

public void inserir(PregaoVO pregaoVO) throws Exception{
try{
openConnection();
String query = "INSERT INTO TB_PREGAO (CODIGO, DESCRICAO, DATA_CRIACAO) VALUES (NULL, ?, ?)";
prepararedStatement = connection.prepareStatement(query);
prepararedStatement.setString(1, pregaoVO.getDescricao());
prepararedStatement.setDate(2, new Date(pregaoVO.getDataCriacao().getTime()));
prepararedStatement.execute();
} catch (SQLException sqle){
sqle.printStackTrace();
} finally {
closeConnections(connection, prepararedStatement, resultSet);
}
}

Tentei de várias formas recuperar o código que a coluna auto increment gerava, pesquisando achei a forma correta de realizar esse tipo de operação. Criei um método que resolve meu problema, adotando essa solução.

public Integer obtemUltimoCodigo(PreparedStatement preparedStatement, ResultSet resultSet) throws Exception{
try{
resultSet = prepararedStatement.executeQuery("SELECT LAST_INSERT_ID()");
while(resultSet.next()){
return resultSet.getInt(1);
}
} catch (SQLException sqle){
sqle.printStackTrace();
}
return null;
}

Esse método recupera o código gerado pela coluna autoincrement do último insert feito. Mas, agora voce deve estar pensando. Será que com requisições simultâneas os códigos não se confudem, por exemplo: o usuário A manda gravar um registro no banco, um código é gerado. O usuário B manda gravar um outro registro no banco quase no mesmo tempo ou no mesmo tempo que o usuário A. Será que o MySql não vai confundir os códigos e retornar os códigos errados? Vendo a documentação essa dúvida foi sanada.

"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."

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Essa parte da documentação da função LAST_INSERT_ID() diz que o código retornado pelo comando é o código gerado pelo último insert relacionado à quem iniciou o processo de inserção. O MySql diferencia os códigos e não faz confusão pq cada sessão aberta no banco é diferente, por isso no metodo obtemUltimoCodigo é passado o preparedStatement e o resultSet. Esses dois objetos são gerados a partir da conexão aberta pela método inserir que chama o obtemUltimoCodigo. Com o método obtemUltimoCodigo o método inserir fica assim:

public void inserir(PregaoVO pregaoVO) throws Exception{
try{
openConnection();
String query = "INSERT INTO TB_PREGAO (CODIGO, DESCRICAO, DATA_CRIACAO) VALUES (NULL, ?, ?)";
prepararedStatement = connection.prepareStatement(query);
prepararedStatement.setString(1, pregaoVO.getDescricao());
prepararedStatement.setDate(2, new Date(pregaoVO.getDataCriacao().getTime()));
prepararedStatement.execute();
pregaoVO.setCodigo(obtemUltimoCodigo(prepararedStatement, resultSet));
} catch (SQLException sqle){
sqle.printStackTrace();
} finally {
closeConnections(connection, prepararedStatement, resultSet);
}
}

Espero ter ajudado =D.

Não gostou ? Tem alguma coisa errada ? Dê sua opinião e comente =D.

3 comentários:

Anônimo disse...

Mto útil, obrigado por compartilhar!

Preciso estudar sempre disse...

Grato pelo elogio meu amigo !

Matheus disse...

Muito Obrigado! Me ajudou muito :D