ResultSet is not positioned correctly, you may need to call next

0

I am developing a web application using JSP and Servlet and that I register the data of the products in the database and present the data in a table, but when I try to see the image registered by the primary key the description http://localhost:8080/EccomerceJSP2/produto/imagens?descricao=effefetu it presents the error .

HTTP Status 500 - org.postgresql.util.PSQLException: ResultSet não está posicionado corretamente, talvez você precise chamar next.

java.lang.RuntimeException: org.postgresql.util.PSQLException: ResultSet não está posicionado corretamente, talvez você precise chamar next.
Model.ProdutosDAO.lerImagem(ProdutosDAO.java:108)
Controler.ImagemProdutosServlet.doGet(ImagemProdutosServlet.java:72)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
  root cause

  org.postgresql.util.PSQLException: ResultSet não está posicionado 
  corretamente, talvez você precise chamar next.
org.postgresql.jdbc.PgResultSet.checkResultSet(PgResultSet.java:2770)
org.postgresql.jdbc.PgResultSet.getString(PgResultSet.java:1893)
org.postgresql.jdbc.PgResultSet.getString(PgResultSet.java:2478)
Model.ProdutosDAO.lerImagemRetorno(ProdutosDAO.java:62)
Model.ProdutosDAO.lerImagem(ProdutosDAO.java:105)
Controler.ImagemProdutosServlet.doGet(ImagemProdutosServlet.java:72)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

Products

Connection con;
ResultSet rs;
PreparedStatement pst;

 private static final String LISTAR_SQL = "SELECT prod_cod, prod_nome, prod_desc, prod_valor, prod_marca, prod_tamanho,prod_tecido, prod_imagem ,prod_tipo_imagem FROM tb_produtos";

private static final String POR_ID_SQL = "SELECT prod_cod, prod_nome, prod_desc, prod_valor, prod_marca, prod_tamanho, prod_parcela, prod_tecido FROM tb_produtos WHERE prod_desc = ?";

private static final String IMAGEM_SQL = "SELECT prod_tipo_imagem, prod_imagem FROM tb_produtos WHERE prod_desc = ?";

private static final String INSERT_SQL = "INSERT INTO tb_produtos (prod_nome, prod_desc, prod_valor, prod_marca, prod_tamanho, prod_tecido, prod_imagem ,prod_tipo_imagem) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";

private static final ProdutosDAO singleton = new ProdutosDAO();//criar objetos únicos para os quais há apenas uma instância. Este padrão oferece um ponto de acesso global, assim como uma variável global, porém sem as desvantagens das variáveis globais.

public ProdutosDAO() {
}


 public static ProdutosDAO instancia() {
     return singleton;
}

private Produtos lerProduto(ResultSet rs) throws SQLException {
    int codigo = rs.getInt("prod_cod");
     String nome = rs.getString("prod_nome");
    String descricao = rs.getString("prod_desc");
    double valor = rs.getDouble("prod_valor");
    String marca = rs.getString("prod_marca");
    String tamanho = rs.getString("prod_tamanho");
    //int parcelas = rs.getInt("prod_parcela");
    String tecido = rs.getString("prod_tecido");
    //String tipo = rs.getString("tipo");
    return new Produtos(codigo,nome, descricao, valor, marca, tamanho, tecido);
}



private ImagemProdutos lerImagemRetorno(ResultSet rs) throws SQLException {

    String tipo = rs.getString("prod_tipo_imagem");
    byte[] conteudo = rs.getBytes("prod_imagem");
    return new ImagemProdutos(tipo, conteudo);
}

public List<Produtos> listarTodos() throws ClassNotFoundException {
    try (
        Connection con = Conecta.conexao();
        PreparedStatement ps = con.prepareStatement(LISTAR_SQL);
        ResultSet rs = ps.executeQuery();
    ) {
        List<Produtos> lista = new ArrayList<>(); 
        while (rs.next()) {
            lista.add(lerProduto(rs));
        }
        return lista;
    } catch (SQLException e) {
       throw new RuntimeException(e);
    }
}


public Produtos lerProduto(String descricao) throws ClassNotFoundException {
    try (
        Connection con = Conecta.conexao();
        PreparedStatement ps = con.prepareStatement(POR_ID_SQL);
    ) {
        ps.setString(1, descricao);
        try (ResultSet rs = ps.executeQuery()) {
            return lerProduto(rs);
        }
    } catch (SQLException e) {
       throw new RuntimeException(e);
    }
}

public ImagemProdutos lerImagem(String descricao) throws ClassNotFoundException {
    try (
        Connection con = Conecta.conexao();
        PreparedStatement ps = con.prepareStatement(IMAGEM_SQL);
    ) {
        ps.setString(1, descricao);
        try (ResultSet rs = ps.executeQuery()) {
            return lerImagemRetorno(rs);
        }
    } catch (SQLException e) {
       throw new RuntimeException(e);
    }
}


 public void salvar(Produtos pro, ImagemProdutos im) {
    try (
        Connection con = Conecta.conexao();
        PreparedStatement ps = con.prepareStatement(INSERT_SQL);
    ) {

        ps.setString(1, pro.getNome());
        ps.setString(2, pro.getDescricao());
        ps.setDouble(3, pro.getValor());
        ps.setString(4, pro.getMarca());
        ps.setString(5, pro.getTamanho());
        ps.setString(6, pro.getTecido());
        ps.setBytes(7, im.getConteudo());
        ps.setString(8, im.getFormato());


        ps.execute();
    } catch (SQLException e) {
       throw new RuntimeException(e);
    } catch (ClassNotFoundException ex) {
         Logger.getLogger(ProdutosDAO.class.getName()).log(Level.SEVERE, null, ex);
     }
}

Servlet responsible for registration

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    int codigo = 0;

    String nome = request.getParameter("nome");

   // do {
     //   codigo++;

   // } while (nome != null);


String descricao = request.getParameter("descricao");
double valor = Double.parseDouble(request.getParameter("valor"));
String marca = request.getParameter("marca");
String tamanho = request.getParameter("tamanho");

String tecido = request.getParameter("tecido");

Part imagePart = request.getPart("file");
String tipo = getFileType(imagePart);
byte[] conteudo = imagePart == null ? new byte[0] : getBytesFromInputStream(imagePart.getInputStream());

Produtos p = new Produtos(codigo, nome, descricao, valor, marca, tamanho, tecido);
ImagemProdutos im = new ImagemProdutos(tipo, conteudo);

ProdutosDAO.instancia ()
.salvar(p, im);

    RequestDispatcher dispatcher = request.getRequestDispatcher("/produtos/listar");

dispatcher.forward (request, response);

 }

 private String getFileType(Part part) {
    if (part == null) return "";
    String partHeader = part.getHeader("content-disposition");
    for (String content : partHeader.split(";")) {
        String trimmedContent = content.trim();
        if (trimmedContent.startsWith("filename")) {
            String nomeEntreAspas = trimmedContent.substring(trimmedContent.indexOf('=') + 1);
            String nomeDoArquivo = nomeEntreAspas.trim().replace("\"", "");
            String extensao = nomeDoArquivo.substring(nomeDoArquivo.indexOf('.') + 1);
            return extensao;
        }
    }
    return null;
}


public static byte[] getBytesFromInputStream(InputStream is) throws IOException {

    try {

         ByteArrayOutputStream os = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 1024];

        int len;
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }

        return os.toByteArray();
    }catch (Exception e) {
    }
    return null;

    } 

Servlet responsible for displaying image by primary key description

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    //a imagem deve ser eniada por url, em uma servlet separada propria

    try {
      String descricao= request.getParameter("descricao");
        Model.ImagemProdutos ip = ProdutosDAO.instancia().lerImagem(descricao);
        response.setContentType("image/" + ip.getFormato());
        response.getOutputStream().write(ip.getConteudo());



    } catch (ClassNotFoundException ex) {
        Logger.getLogger(ImagemProdutosServlet.class.getName()).log(Level.SEVERE, null, ex);
    }
}

JSP

<h3>Lista de Produtos Cadastrados</h3>

      <table border="1">
      <tr>
          <th>Codigo</th> 
          <th>Produto</th>
           <th>Nome</th>
           <th>Descricao</th>
           <th>Valor</th>
           <th>Marca</th>
           <th>Tamanho</th>

          <th>Tecido</th>

      </tr>


      <c:forEach items="${requestScope.produtos}" var="registro">

          <tr>
              <td> <c:out value="${registro.codigo}"/></td>
              <td> <img src="<c:url value="/produto/imagens?descricao=${registro.descricao}"/>"</td>
              <td> <c:out value="${registro.nome}"/></td>
              <td> <c:out value="${registro.descricao}"/></td>
              <td> <c:out value="${registro.valor}"/></td>
              <td> <c:out value="${registro.marca}"/></td>
              <td> <c:out value="${registro.tamanho}"/></td>

              <td> <c:out value="${registro.tecido}"/></td>

          </tr>


      </c:forEach>

  </table> 
    
asked by anonymous 01.11.2017 / 15:45

1 answer

0

The error message is telling you exactly what the problem is. See:

In the lerImagem() method you do:

try (ResultSet rs = ps.executeQuery()) {
    return lerImagemRetorno(rs);
}

O in the lerImagemRetorno() method you do:

String tipo = rs.getString("prod_tipo_imagem");
byte[] conteudo = rs.getBytes("prod_imagem");
return new ImagemProdutos(tipo, conteudo);

Notice that at no time does the method next() of ResultSet is called.

Since ResultSet rs will always return a result for this case, you can do:

try (ResultSet rs = ps.executeQuery()) {
    while(rs.next()) {
        return lerImagemRetorno(rs);
    }
}

However, for cases where the ResultSet returns more than one record, one must work with some type of collection ( List , Set and etc).

But regardless of that, the main point is to call the next() method as it moves the "reading position" of the ResultSet to the next position.

Method documentation next() starts with:

  

Moves the cursor froward one row from its current position

Since the return documentation says:

  

Returns: true if the new current row is valid; false if there are no more rows

That is, if the next() method is invoked but no more records exist, the false value is returned.

That's why we put the call of this method inside a while .

    
01.11.2017 / 16:14