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

Asked

Viewed 394 times

0

I am developing a web application using JSP and Servlet and that registers the product data in the database and present the data in a table, but when trying 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)

Productosdao

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 the 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 the image by the primary key

  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> 
  • The ResultSet gets positioned before the first line of results. You must invoke rs.next() before you start reading the data.

1 answer

0


The error message is saying exactly what the problem is. See:

In the method lerImagem() you do:

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

The in the method lerImagemRetorno() you do:

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

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


whereas the Resultset rs will always return a result for this case, you can do:

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

With everything, for cases where Resultset returns more than one record one must work with some kind of collection (List, Set and etc).

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


Documentation of the method next() begins with:

Moves the cursor froward one Row from its Current position

And the return documentation says:

Returns: true if the new Current Row is Valid; false if there are no more Rows

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

That is precisely why we put the call of this method within a while.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.