DAO, sei que to fazendo caca, mas como melhorar isso?

5 respostas
asclows

Como eu faria a persistência no caso abaixo onde tenho um objeto curriculo o qual possui alguns atributos que são List que serão armazenados em uma tabela curriculo_categoria (muito-para-muitos entre curriculo e categoria), sei que estou fazendo mal e porcamente no entanto ainda não sei uma forma legal de se fazer isso, segue abaixo o código.

public void create(Curriculo curriculo) throws SQLException {
        String campos;
        String query;
        PreparedStatement stmt;
        ResultSet rs;
        Long lastId = 0l;
        
        campos = "objetivo, pretensaoSalarial, escolaridade, outraExperiencia," +
                "outraLinguagem, outroBancoDados, outroBusinessIntelligence, " +
                "outroErp, anexo";
        
        query  = "INSERT INTO curriculo (" + campos + ") " +
                 "VALUES (?,?,?,?,?,?,?,?,?)";
        
        stmt  = connection.prepareStatement(query);
        stmt.setString(1, curriculo.getObjetivo());        
        stmt.setDouble(2, curriculo.getPretensaoSalarial());   
        stmt.setLong(3, curriculo.getEscolaridade().getId());
        stmt.setString(4, curriculo.getOutraExperiencia());
        stmt.setString(5, curriculo.getOutraLinguagem());
        stmt.setString(6, curriculo.getOutroBancoDados());
        stmt.setString(8, curriculo.getOutroBusinessIntelligence());
        stmt.setString(9, curriculo.getOutroErp());
        stmt.setString(10, curriculo.getAnexo());
        
        // executa
        stmt.execute();
        stmt.close();
        
        query  = "SELECT MAX(id) FROM curriculo";
        stmt   = connection.prepareStatement(query);
        rs     = stmt.executeQuery();
        
        if (rs.next()) {
            lastId = rs.getLong(0);      
        }
        
        rs.close();
        stmt.close();
        
        if (lastId != 0l) {
            query = "INSERT INTO curriculo_categoria VALUES(?, ?)";
            stmt  = connection.prepareStatement(query);            
            
            for (int i = 0; i < curriculo.getExperiencias().size(); i++) {
                stmt.clearParameters();
                stmt.setLong(0, lastId);
                stmt.setLong(1, curriculo.getExperiencias().get(i).getId());
                stmt.execute();
            }
            
            // demais insercoes de colecao na tabela curriculo_categoria
            
            stmt.close();            
        }
    }

Qualquer contribuição já é bem-vinda!

Sei que utilizar o hibernate resolveria isto facilmente, mas como o projeto já está em andamento vou ter que persistir com DAOs SQL mesmo. E também porque quero matar de vez minhas dúvidas sobre isto.

5 Respostas

Pedrosa

Tome cuidado com esse tipo de código, pode ocorrer mais de um insert e seu esquema vai por água a baixo o lance do select max, talvez se seu método fosse syncronized poderia garantir que se executasse um de cada vez, mas realmente não sei se essa é a melhor solução.

leassis

ENtão como dito anteriormente por nosso amigo, vc terá o problema de usar o mesmo id para dois registros, o que provavelmente (certamente) vai violar sua pk.

Eu sugiro que vc faça um método private syncronized para isso assim vc não terá esse problema, claro que vai diminuir um pouco a performance.

Outra alternativa é dar uma olhada na api na classe java.sql.Statement e procurar pelo método getGeneratedKeys ele retorna o que vc precisa.

Thiago_Senna

Minhas sugestões seriam as seguintes:

Dê uma olhada no commons-dbutils: http://jakarta.apache.org/commons/dbutils/

Você não precisa necessariamente utilizar a api. Estude o código fonte, enteda-o e aplique-o. Lá já tem várias coisas legais e consequentemente sugestões para você dar um bom upgrade no exemplo que você passou.

Pessoalmente gosto de capturar as ‘checked exeptions’ (SQLException por exemplo) e relançar como uma ‘uncheked exeption’ (DAOException).

Outra opção é você dar uma olhada no suporte a JDBC do Spring, ou seja, utilizar o JdbcTemplate.
http://www.springframework.org/docs/reference/jdbc.html

raci0nal

Qual SGBD você está usando?

Você pode incluir essa geração de código direto na SQL.
Recomendavelmente você usaria campos sequenciais (ou generators dependendo do SGBD).
No Firebird, por exemplo ficaria:

"INSERT INTO tabela (codigo, nome, outros...) VALUES (GEN_ID(gen_tabela_id, 1), "nome", "outros"...)"
O SGBD se encarrega de gerar os números não permitindo NUNCA que se repitam.
Outra opção, mantendo a sua lógica:

"INSERT INTO tabela (codigo, nome, outros...) VALUES ((SELECT max(codigo) FROM tabela), "nome", "outros"...)"
Contudo recomendo o uso de GENERATORS.

Marcos A. C. Jordão’’

cv1

Se nada mais der certo, pelo menos vc pode usar o JdbcTemplate do Spring, pra diminuir a quantidade de codigo repetido. :wink:

Criado 2 de julho de 2007
Ultima resposta 2 de jul. de 2007
Respostas 5
Participantes 6