Gravar arquivo em campo BLOB mysql, usando java

Ola … sou iniciante em Java e estou aprendendo desenvolvendo uma ferramenta.

Gostaria de ajuda para salvar um arquivo qq no meu banco de dados em um campo BLOB. E também como resgatar o mesmo.

O que tenho pronto é:

Metodo para escolher o arquivo …

    JFileChooser vOpen = new JFileChooser();
    int vRetorno = vOpen.showOpenDialog(null);  

    if (vRetorno==JFileChooser.APPROVE_OPTION) {
        txtModel.setText(vOpen.getSelectedFile().getAbsolutePath().toString());

Depois quando vou salvar transformo o arquivo em byte[] na variavel vFileBytes
File vFile = new File(txtModel.getText());
byte[] vFileBytes = new byte[(int)vFile.length()];
int vOffSet = 0;
int vNumRead = 0;

    try {
        InputStream vIS = new FileInputStream( vFile );
        while (vOffSet < vFileBytes.length && (vNumRead = vIS.read(vFileBytes, vOffSet, vFileBytes.length-vOffSet)) >= 0) {
            vOffSet += vNumRead;
        }
    } catch (FileNotFoundException ex) {
        Logger.getLogger(frmDocumentType.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(frmDocumentType.class.getName()).log(Level.SEVERE, null, ex);
    }

    objDocumentType.metCreateSQLCommands(vAction, txtId.getText(), txtCode.getText(), txtName.getText(), vFileBytes, null);

Onde nesse caso,chamei um outro metodo para criar a string com o insert … (nao estou colocando tudo, apenas parte que envolve o campo que desejo ajuda)

public void metCreateSQLCommands(String pAction, String pId, String pCode, String pName, byte[] pModel, String pDeleteReason)

       vInsertUpdateDelete = "insert into tblDocumentType (Code, " +
                              "                             Name, " +
                              "                             Model, " +
                              "                             AddDateTime, " +
                              "                             AddUserId, " +
                              "                             UpdateDateTime, " +
                              "                             UpdateUserId, " +
                              "                             DeleteDateTime, " +
                              "                             DeleteUserId) ";
        if (pCode.equals("")) {
            vInsertUpdateDelete = vInsertUpdateDelete + "values ( null, ";
        } else {
            vInsertUpdateDelete = vInsertUpdateDelete + "values ('"+pCode+"', ";
        }

        if (pName.equals("")) {
            vInsertUpdateDelete = vInsertUpdateDelete + " null, ";
        } else {
            vInsertUpdateDelete = vInsertUpdateDelete + " '"+pName+"', ";
        }

        if (pModel.equals("")) {
            vInsertUpdateDelete = vInsertUpdateDelete + " null, ";
        } else {
            vInsertUpdateDelete = vInsertUpdateDelete + " " + pModel + ", ";

Apos isso todo a execução desse string com o comando insert

    try {
        vDatabase.getvStatement().executeUpdate(vInsertUpdateDelete);
        vDatabase.getvConnection().commit();
        vResult = true;
    } catch (SQLException vSQLE) {
        try {
            vDatabase.getvConnection().rollback();
        } catch (SQLException vSQLEi) {
            JOptionPane.showMessageDialog(null, "Error in rollback command:\n" + vInsertUpdateDelete + "\n Details:" + vSQLEi);
        }

        JOptionPane.showMessageDialog(null, "Could not execute SQL command:\n" + vInsertUpdateDelete + "\n Details:" + vSQLE);
    }

O que faço errado? Se rodo dessa maneira me da erro de execução no SQL … se coloco aspas simples no campo blob, grava como texto … o que fazer? Se puderem ,… como recuperar depois tambem

Bom dia,
segue uma dica que pode lhe ajudar: Não concatene os dados a serem gravado no comando SQL(String). Sempre que precisar inserir valores dinamicos em uma SQL utilize o PreparedStatement passando todos valores como parâmetro. Assim o próprio jdbc fará a devida conversão e evita sql injection. Pois do jeito que vc está fazendo, se tiver uma aspa em algum valor já vai dar crash.

OK …entendi o que comentou sobre o PreparedStatement. Porém tenho algumas dúvidas, no sistema tenho 3 camadas: Forms, Business e Database.

Dentro da classe de banco de dados, tenho um método que irá executar o PreparedStatement.execute() … irá executar um PreparedStatement que foi setado na camada de Business, onde foi criada a query a ser executada e informado os parametros.

Como você aconselha eu criar essa rotina?

Ao rodar o execute() no catch eu mostrava a query que foi executada, e agora como pego isso?

Obrigado

Ola,
Acredito que suas camadas estão furadas. Não recomendo passar objetos de banco da camada de cima pra do banco.
Na classe do banco (DAO se estiver usando) vc faz um método save que receberá o objeto a ser salvo. Este método deverá criar a query, o preparedstatement, setar os parametros e executar.

Fiz algumas mudanças no meu código e gostaria de voltar nesse assunto pois ainda continuo com o problema de gravar um arquivo no campo blob em uma base MYSQL.

Tenho um campo chamado “Model” do tipo BLOB em ma tabela X em um banco de dados MySQL.

Eu gostaria de uma aplicação java gravar um arquivo (doc, xls, pdf, etc) neste campo.

O código que eu irei colocar abaixo, peguei parte na internet, mas para mim está errado e ai que entra meu pedido de ajuda.

No meu formulário, clico em um botão para escolher o arquivo:

    JFileChooser vOpen = new JFileChooser();
    int vRetorno = vOpen.showOpenDialog(null);  

    if (vRetorno==JFileChooser.APPROVE_OPTION) {
        txtModel.setText(vOpen.getSelectedFile().getAbsolutePath().toString());
    }

Depois de preencher os campos necessários, clico em um botão para salvar:
//objMdlDocumentType - é a classe modelo
//objCntDocumentType - é a classe controle

    File vFile = new File(txtModel.getText());
    byte[] vFileBytes = new byte[(int)vFile.length()];
    int vOffSet = 0;
    int vNumRead = 0;

    try {
        InputStream vIS = new FileInputStream( vFile );
        while (vOffSet < vFileBytes.length && (vNumRead = vIS.read(vFileBytes, vOffSet, vFileBytes.length-vOffSet)) >= 0) {
            vOffSet += vNumRead;
        }
    } catch (FileNotFoundException ex) {
        Logger.getLogger(frmDocumentType.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(frmDocumentType.class.getName()).log(Level.SEVERE, null, ex);
    }

    if (vAction.equals("U")) {
        objMdlDocumentType.setId(Integer.parseInt(txtId.getText()));
    }
    objMdlDocumentType.setCode(txtCode.getText());
    objMdlDocumentType.setName(txtName.getText());
    objMdlDocumentType.setModel(vFileBytes); //seta uma variavel do tipo byte[]

    objCntDocumentType.setMdlDocumentType(objMdlDocumentType); //passo a classe modelo para a classe controle para mandar gravar na linha abaixo
    if (objCntDocumentType.metSave(vAction)) {
        vAction = "S";
        metEnableFilters();
        metClearTable();
        metUpdateGrid();
        metEnableButtons(vAction);
    } else {
        txtCode.requestFocus();
    }

Dentro da classe de controle, ele chama um método para fazer o insert:

    try {
        PreparedStatement vPS = objMdlDocumentType.getDtbDatabase().getConnection().prepareStatement(objMdlDocumentType.getInsert());
        vPS.setString(1, objMdlDocumentType.getCode());
        vPS.setString(2, objMdlDocumentType.getName());
        vPS.setBytes(3, objMdlDocumentType.getModel());
        vPS.setInt(4, objMdlDocumentType.getDtbDatabase().getUserIdConnected());
        vPS.execute();
        vReturn = true;
    } catch (SQLException vSE) {
        JOptionPane.showMessageDialog(null, "Inserting error into tblDocumentType table.\nError Message.:" + vSE);
    }

No teste que fiz, ao escolher um arquivo que estava c:\users\ZG\documentos com o nome teste.jpg com o tamanho de 80kb, ocorreu o erro "com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column ‘Model’ at row 1.

Podem me ajudar?

Muito obrigado.

Segue esse exemplo: