两亩三分地

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  17 随笔 :: 20 文章 :: 2 评论 :: 0 Trackbacks
相对于上一篇的CategoryServlet,BlogServlet相对复杂一些。
不如在做添加博文的时候,我们要考虑的不仅仅是blog本身的主题,内容还要考虑blog所对应的类别;
一般我们把类别做成一个List以供选择。所以在blog添加的前,我们首先要处理category信息,那么
如果要添加blog的话,首先要做的是预处理category。
 1 private void preAdd(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         List categories = null;
 4         String sql = "select id,name from category order by name";
 5         QueryRunner qr = DbHelper.getQueryRunner();
 6         try {
 7             categories = (List) qr.query(sql, new BeanListHandler(Category.class));
 8         } catch (SQLException ex) {
 9             Logger.getLogger(BlogServlet.class.getName()).log(Level.SEVERE, null, ex);
10         }
11         request.setAttribute("categories", categories);
12         request.getRequestDispatcher("/admin/addBlog.jsp").forward(request, response);
13     }
从code上看,预处理与blog类并没有关系,而是针对category的。

在list所有blog记录的时候,我们同样要考虑到category信息,
 1 private void list(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3         String sql = "select b.id as id,title,content,date,c.name as category, c.id as categoryId from blog b,category c where category_id=c.id order by b.date desc";
 4         QueryRunner qr = DbHelper.getQueryRunner();
 5         List blogs = null;
 6         try {
 7             blogs = (List) qr.query(sql, new BeanListHandler(Blog.class));
 8         } catch (SQLException ex) {
 9             Logger.getLogger(BlogServlet.class.getName()).log(Level.SEVERE, null, ex);
10         }
11         request.setAttribute("blogs", blogs);
12         request.getRequestDispatcher("/admin/adminBlogList.jsp").forward(request, response);
13     }
第3行的sql语句将blog表与category表关联起来,运行该SQL命令也成功找到相应的数据;但是在程序里,对应的JSP显示却不成功,与blog相关的数据正确,但是与categoryId对应的
category name(程序中的Blog类里的category)没有显示出来,数据显示是null。
这是因为DbUtils 在做表到对象的映射时要求列名和对象的属性名必须一致,也就是说对应blog类里的category属性正确的名称应该是name。
所以当
String sql = "select b.id as id,title,content,date,c.name as category, c.id as categoryId from blog b,category c where category_id=c.id order by b.date desc";
QueryRunner不能将数据映射到category属性里。在发现并解决了DbUtils项目的一个问题指出,问题的关键是DbUtils在处理数据表的时候是使用getColumnName()方法
BasicRowProcessor.java
 1 /** 
 2      * Convert a <code>ResultSet</code> row into a <code>Map</code>.  This 
 3      * implementation returns a <code>Map</code> with case insensitive column
 4      * names as keys.  Calls to <code>map.get("COL")</code> and 
 5      * <code>map.get("col")</code> return the same value.
 6      * @see org.apache.commons.dbutils.RowProcessor#toMap(java.sql.ResultSet)
 7      */
 8     public Map toMap(ResultSet rs) throws SQLException {
 9         Map result = new CaseInsensitiveHashMap();
10         ResultSetMetaData rsmd = rs.getMetaData();
11         int cols = rsmd.getColumnCount();
12 
13         for (int i = 1; i <= cols; i++) {
14             result.put(rsmd.getColumnName(i), rs.getObject(i));
15         }
16 
17         return result;
18     }
BeanProcessor.java
 1     /**
 2      * The positions in the returned array represent column numbers.  The 
 3      * values stored at each position represent the index in the 
 4      * <code>PropertyDescriptor[]</code> for the bean property that matches 
 5      * the column name.  If no bean property was found for a column, the 
 6      * position is set to <code>PROPERTY_NOT_FOUND</code>.
 7      * 
 8      * @param rsmd The <code>ResultSetMetaData</code> containing column 
 9      * information.
10      * 
11      * @param props The bean property descriptors.
12      * 
13      * @throws SQLException if a database access error occurs
14      *
15      * @return An int[] with column index to property index mappings.  The 0th 
16      * element is meaningless because JDBC column indexing starts at 1.
17      */
18     protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
19             PropertyDescriptor[] props) throws SQLException {
20 
21         int cols = rsmd.getColumnCount();
22         int columnToProperty[] = new int[cols + 1];
23         Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);
24 
25         for (int col = 1; col <= cols; col++) {
26             String columnName = rsmd.getColumnName(col);
27             for (int i = 0; i < props.length; i++) {
28 
29                 if (columnName.equalsIgnoreCase(props[i].getName())) {
30                     columnToProperty[col] = i;
31                     break;
32                 }
33             }
34         }
35 
36         return columnToProperty;
37     }
以上2段程序 读了就会发现问题所在了。DbUtils利用getColumnName()来处理列名,所以类似c.name as category, c.id as categoryId的语句并不适用与DbUtils。
解决的方法就是将以上2段程序中的getColumnName()方法改成getColumnLabel(),然后重新编译DbUtils源文件。然后将fixed的DbUtils文件重新加入库就可以解决问题了。
commons-dbutils-1.2_fixed.jar

BlogServlet中其他方法就不一一介绍了。





posted on 2009-09-29 13:52 Chucky 阅读(116) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: