【问题标题】:sql for paging notice board in jspjsp中分页布告栏的sql
【发布时间】:2023-03-03 11:54:01
【问题描述】:

我正在尝试制作一个公告板,并且在应用分页功能之前它可以很好地显示帖子。

但在我应用分页功能后,它只显示一个帖子,分页功能可以很好地显示页面。

所以我认为这是一个 sql 问题。 当我尝试显示计数时,它显示 1。即使我尝试过显示 1。

sql = "select * from mvc_board ";

这是我的 sql

 String sql = "SELECT ROWNUM, bId, bName, bTitle, bContent," +
               "bDate, bHit, bGroup, bStep, bIndent " +
               "from(select * from mvc_board order by bGroup DESC , bStep asc)";

我试图用这个 sql 制作我的。但看不懂。

sql = "select *, (select u_name from user where idx = writer_fk) writer, (select idx from answer where idx = answer_fk) answer from board order by idx desc limit "+startRow+", "+endRow;

参考。 http://queserasera.tistory.com/14

这是 DAO

  public ArrayList<BDto> getBoardList(int startRow, int endRow, String keyField, String keyWord) {
        ArrayList<BDto> dtos = new ArrayList<BDto>();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        String sql = "SELECT ROWNUM, bId, bName, bTitle, bContent," +
               "bDate, bHit, bGroup, bStep, bIndent " +
               "from(select * from mvc_board order by bGroup DESC , bStep asc)";
       System.out.println(sql);
         try{
            if(keyWord != null && !keyWord.equals("") && !keyWord.equals("null")) {
                sql += " WHERE " + keyField.trim() +" LIKE '%"+keyWord.trim()+"%'";
            }


           connection =  dataSource.getConnection();

           //특정행부터  레코드를 가져오기 위해서 옵션 설정
           preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();

           while(resultSet.next()){

             int count=0;

                int ROWNUM = resultSet.getInt("ROWNUM");
                int bId = resultSet.getInt("bId");
                String bName = resultSet.getString("bName");
                String bTitle = resultSet.getString("bTitle");
                String bContent = resultSet.getString("bContent");
                Timestamp bDate = resultSet.getTimestamp("bDate");
                int bHit = resultSet.getInt("bHit");
                int bGroup = resultSet.getInt("bGroup");
                int bStep = resultSet.getInt("bStep");
                int bIndent = resultSet.getInt("bIndent");

                BDto dto = new BDto(ROWNUM, bId, bName, bTitle, bContent, bDate, bHit, bGroup, bStep, bIndent);
                dtos.add(dto);

                  count++;
                  System.out.println(count);
             //while문끝

           }//if문끝


        }catch (Exception e) {
           System.out.println(e+"=> getBoardList fail");
       }finally {
            try {
                if(resultSet != null) resultSet.close();
                if(preparedStatement != null) preparedStatement.close();
                if(connection != null) connection.close();
            } catch (Exception e2) {
                // TODO: handle exception
                e2.printStackTrace();
            }
        }

       return dtos;
   }

=============在sql developer上添加sql============================= =====

select rn, bId, bName, bTitle, bContent, bDate, bHit, bGroup, bStep, bIndent 
from ( select b.*, row_number() over (order by bGroup DESC, bStep asc) rn
from mvc_board b %s ) 
where rn between 1 and 10
order by rn;

【问题讨论】:

  • 您使用的是哪个 Oracle 版本?
  • @MickMnemonic 11g!
  • 请分享getTotalRecord()的代码
  • @MickMnemonic 我添加了!谢谢!
  • 对了,你怎么知道mvc_board有多行?

标签: java sql oracle jsp oracle11g


【解决方案1】:

在您给我们的示例中,分页是由limit 子句添加的,但ORACLE 有它自己的语法。试试:

 String sql = "SELECT rown, bId, bName, bTitle, bContent," +
              "bDate, bHit, bGroup, bStep, bIndent " +
              "from(select rownum rown, mvc_board.* from mvc_board order by bGroup DESC , bStep asc) " +
              "WHERE rown between ? and ? ";

在执行查询之前绑定startRowendRow

preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,startRow);
preparedStatement.setInt(2,endRow);
resultSet = preparedStatement.executeQuery();

WHERE 更改为AND

sql +=" and " + keyField.trim()+" LIKE '%"+keyWord.trim()+"%'" ;

最后将if(resultSet.next()){ 改回while 循环以获得多于一行的结果。

【讨论】:

  • 用那个我无法理解的 sql。因为我不知道什么 u_name, writer_fk, writer, answer_fk, answer .. 所以现在我使用 String sql = "SELECT ROWNUM, bId, bName, bTitle, bContent," + "bDate, bHit, bGroup, bStep, bIndent " + "from(select * from mvc_board order by bGroup DESC , bStep asc)";
  • 我也试着做 这仍然在 jsp 上显示 1post。所以我添加了 list.jsp 和 BListCommand.java !
  • OP 正在使用 Oracle 11g,其中 row-limiting clause 尚不可用。
【解决方案2】:

getBoardList() 方法中的主要问题是在遍历结果集时使用了if (resultSet.next()) 而不是while (resultSet.next());这导致代码只返回一个 DTO。

您还应该考虑其他事项。例如,从 Java 7 开始,最好使用 try-with resources statement 而不是传统的 try-finally 进行 JDBC 资源处理。

需要注意的重要一点是,从 UI 中注入像 keyField 这样的字段名称是一种非常糟糕的做法,因为它会使查询容易受到 SQL injection 的攻击。 如果您不能使用静态 WHERE 条件,您至少应该创建一个允许字段名称的静态白名单来清理输入。

最后,Oracle 11g 中的分页查询传统上是通过使用row_number analytic function 的内联视图完成的。注意行号从1开始。从Oracle 12c开始,可以使用the row-limiting clause,不再需要内联视图。

考虑以上几点的示例实现可能如下所示:

 public List<BDto> getBoardList(int startRow, int endRow, String keyField, String keyWord) {

    List<BDto> dtos = new ArrayList<BDto>();

    // the %s in the template will be replaced with a 
    // WHERE condition when a keyword is present
    final String sqlTemplate = "select rn, bId, bName, bTitle, "
            + "bContent, bDate, bHit, bGroup, bStep, bIndent "
            + "from ( "
            + "     select b.*, row_number() over (order by bGroup DESC, bStep asc) rn" 
            + "    from mvc_board b %s "
            + "    ) "
            + "    where rn between ? and ? "
            + "order by rn";

    boolean whereCondition = false;

    String sql = null;

    if (keyWord != null && !keyWord.equals("") && !keyWord.equals("null")) {
        sql = String.format(sqlTemplate, 
                   " WHERE " + keyField.trim() + " LIKE '%' || ? || '%'");
        whereCondition = true;
    } else {
        sql = String.format(sqlTemplate, "");
    }

    System.out.println(sql);

    try (Connection connection = dataSource.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql)) {

        int parameterIndex = 1;

        if (whereCondition) {
            preparedStatement.setString(parameterIndex++, keyWord);
        }
        preparedStatement.setInt(parameterIndex++, startRow);
        preparedStatement.setInt(parameterIndex, endRow);

        try (ResultSet resultSet = preparedStatement.executeQuery()) {

            int count = 0;

            while (resultSet.next()) {

                int ROWNUM = resultSet.getInt("rn");
                int bId = resultSet.getInt("bId");
                String bName = resultSet.getString("bName");
                String bTitle = resultSet.getString("bTitle");
                String bContent = resultSet.getString("bContent");
                Timestamp bDate = resultSet.getTimestamp("bDate");
                int bHit = resultSet.getInt("bHit");
                int bGroup = resultSet.getInt("bGroup");
                int bStep = resultSet.getInt("bStep");
                int bIndent = resultSet.getInt("bIndent");

                dtos.add(new BDto(ROWNUM, bId, bName, bTitle, 
                        bContent, bDate, bHit, bGroup, bStep, bIndent));

                count++;
            }
            System.out.println(count);
        }

    } catch (SQLException e) {
        System.out.println(e + "=> getBoardList fail");
    }

    return dtos;
}

【讨论】:

  • 效果很好!万分感谢!我又发现了一个问题。当我搜索特定的单词时,它可以很好地显示页面和帖子。但是当我转到第 2 页或下一页时,它没有应用搜索关键字。我不知道如何转移 keyWord&keyField ..!我编辑了 list.jsp 你能检查一下吗?谢谢!
  • 我发布了关于这个的新主题!你也要检查这个吗? stackoverflow.com/questions/52847297/…
  • 嗨,你的代码运行得很好,但是当我尝试使用 sql developer 时它没有工作:(我在下面的帖子中添加了
  • 这是因为如果存在关键字,Java 代码会将 %s 部分替换为 WHERE 条件(请参阅 if (keyWord != null...) 中的块)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多