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.
Leia Mais ››

terça-feira, 3 de janeiro de 2012

Realizando upload com ajax

Mais uma vez tive que resolver um problema bizarro que era, validar uploads. Por validar é possível entender como: validar tamanho dos arquivos, nome, extensão, etc.Quando se faz um upload de um arquivo não é possível usar ajax por motivos de segurança e, geralmente o que envolve inputs do type file e upload é sempre problemático. Procurando por uma solução achei um site que mostra como fazer o upload de arquivos usando iframe simulando uma requisição assíncrona com AJAX.

O site é: http://elmicoxcodes.blogspot.com/2007/03/asynchronous-upload-like-ajax-1.html

O post desse site está em inglês mas, a versão em português está disponível em: http://valeus.net/micox/micoxUpload2.htm
Leia Mais ››

sexta-feira, 23 de dezembro de 2011

Manipulando o display em vários browsers

Manipular elementos css com JavaScript em diferentes browsers é uma tarefa que requer pesquisa, pois o IE possui algumas diferenças em relação aos outros browsers. Hoje, será tratado nesse post a manipulação do elemento css "display" usando JavaScript. Para tornar um elemento visível na tela usando o IE, use:

document.getElementById("idaqui").style.display = "block";

Para ocultá-lo use:

document.getElementById("idaqui").style.display = "none";

Esses comandos funcionam perfeitamente no IE mas, na família Firefox, Chrome, Safari e Opera não funcionam tão bem. Para solucionar esse problema usamos:

Para tornar um elemento visível na tela usando o Firefox, Chrome, Safari e Opera:

document.getElementById("idaqui").style.display = "";

Para ocultá-lo use:

document.getElementById("idaqui").style.display = "none";

Com a manipulação dessa propriedade é possível construir layouts dinâmicos que mudam de acordo com a escolha do usuário.
Leia Mais ››

quarta-feira, 21 de dezembro de 2011

Como descobrir o tamanho de imagens em JavaScript


Trabalhar com pré-carregamento de arquivos na web é um ponto complicado, pois existem diferenças entre os browsers. Por exemplo, o firefox, safari, opera, chrome e o IE (a partir do 7, inclusive) não disponibiliza o caminho completo de um arquivo quando escolhido. O IE 6 possui a particularidade de disponibilizar o path completo de um arquivo mas, como o IE não é mais usado em larga escala não pode ser pego como exemplo. Os navegadores atuais não disponibilizam o caminho completo do arquivo por uma questão de segurança.

Para que possamos entender como podemos realizar o pré-carregamento de arquivos em cache usando JavaScript, vamos criar uma página de exemplo.


pagina-upload.html


<html>
<head>

<script type="text/javascript">
var conteudo = "Tamanho do arquivo: ";
</script>
</head>
<body>
<form action="algumacoisaaqui" method="post" enctype="multipart/form-data">
<input type="file" name="inputfile1" size="70" id="inputfile1" />
<input type="button" name="botaolimpar" id="botaolimpar" value="Remover" title="Remover" onclick="remover()" />
<br/>
<br/>
<input type="button" name="botaocarregar" id="botaocarregar" value="Carregar" title="Carregar" onclick="carregar()" />
<div id="divResultado">

</div>
</form>
</body>
</html>




Essa página possui um campo do tipo file, um botão (botão carregar) para que o pré-carregamento seja feito e um botão para limpar o campo de upload (botão remover). Toda a lógica do pré-carregamento está na função (função carregar) associada ao onclick do botão "Carregar", o botão "Remover" também possui uma função (função remover) associada ao seu evento onclick.

Função carregar

function carregar(){
var inputFile = document.getElementById("inputfile1");
var divResultado = document.getElementById("divResultado");
var limite = 15000;
if(navigator.appName == "Microsoft Internet Explorer"){
var imagem = new Image();
imagem.src = inputFile.value;
var tamanhoArquivo = imagem.fileSize;
if(tamanhoArquivo < 0){
carregar();
} else {
conteudo += tamanhoArquivo + " bytes <br/> Limite Permitido: 15000 bytes <br/>";
if(tamanhoArquivo > limite){
conteudo += "Arquivo acima do limite";
} else {
conteudo += "Arquivo abaixo do limite";
}
}

}else{
conteudo += inputFile.files[0].size + " bytes <br/> Limite Permitido: 15000 bytes <br/>";
if(parseInt(inputFile.files[0].size) > limite){
conteudo += "Arquivo acima do limite";
} else {
conteudo += "Arquivo abaixo do limite";
}
}
divResultado.innerHTML = conteudo;
}

Função remover

function remover(){
var inputFile = document.getElementById("inputfile1");
/* passo false como parametro porque nao quero que os child nodes daquele elemento sejam
clonados, como o input nao possui child nodes passo false*/
var inputFileNovo = inputFile.cloneNode(false); //clono o elemento
inputFileNovo.type = "file";
inputFileNovo.value = "";
inputFile.parentNode.replaceChild(inputFileNovo,inputFile); //troco o input antigo pelo novo
document.getElementById("divResultado").innerHTML = "";
}





É possível notar na função carregar que um tratamento diferenciado é feito se o navegador é IE, esse tratamento é feito porque no IE não é possível manipular direto o elemento do DOM, é necessário que um objeto do tipo Image seja criado. Como nesse exemplo estamos lidando com somente um campo, não é perceptível a queda de performance devido a criação do objeto, causando assim gasto de memória mas, se várias instâncias forem criadas e o pré-carregamento feito em cache, será possível notar a lentidão. Conclusão, realizar o pré-carregamento de arquivos em cache no IE é muito mais custoso do que realizar em outro navegador.
Leia Mais ››