首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

《研磨struts2》第十二章 CRUD综合使用 之 12.2 实现域对象和数据层

2012-08-02 
《研磨struts2》第十二章 CRUD综合运用 之 12.2 实现域对象和数据层12.2??实现域对象和数据层12.2.1??建表和

《研磨struts2》第十二章 CRUD综合运用 之 12.2 实现域对象和数据层

12.2??实现域对象和数据层

12.2.1??建表和域对象

在示例中只需要管理用户的基本信息,用户编号(userId)、姓名(name)、性别(sex)、年龄(age)即可,在mysql中,可以用下面的语句建表:

?

java代码:查看复制到剪贴板打印
  1. create?table?tbl_user(??
  2. ???????userId?int?primary?key,??
  3. ???????name?varchar(20),??
  4. ???????sex?varchar(10),??
  5. ???????age?int??
  6. )?character?set?=gb2312;??

在上面的语句中,建立了一张表叫tbl_user,分别有4个字段:

  • userId:整数类型,是这张表的主键。
  • name:字符类型。注意:varchar后面的20表示这个字段最大可以接受20个字节。
  • sex:字符类型。
  • age:整数类型。

    建表语句后面的“character set =gb2312”,是用来设置该表的字符集,使其能够支持中文,跟在后面连接数据库连接语句里面设置的字符集相对应。

    建表之后,就可以建立与它相对应的域对象了。在建立域对象的时候,通常的实现方式是:表对应域对象的类,表的每个字段对应类中的一个属性并且为这个属性配备相应的getter/setter方法,表中的主键字段要用来生成hashCode方法和equals方法。域对象的示例代码为:

    ?

    java代码:查看复制到剪贴板打印
    1. public?class?UserModel?{??
    2. ????private?int?userId;??
    3. ????private?String?name;??
    4. ????private?String?sex;??
    5. ????private?int?age;??
    6. ??????
    7. ????public?int?getUserId()?{??
    8. ????????return?userId;??
    9. ????}??
    10. ????public?void?setUserId(int?userId)?{??
    11. ????????this.userId?=?userId;??
    12. ????}??
    13. ????public?String?getName()?{??
    14. ????????return?name;??
    15. ????}??
    16. ????public?void?setName(String?name)?{??
    17. ????????this.name?=?name;??
    18. ????}??
    19. ????public?String?getSex()?{??
    20. ????????return?sex;??
    21. ????}??
    22. ????public?void?setSex(String?sex)?{??
    23. ????????this.sex?=?sex;??
    24. ????}??
    25. ????public?int?getAge()?{??
    26. ????????return?age;??
    27. ????}??
    28. ????public?void?setAge(int?age)?{??
    29. ????????this.age?=?age;??
    30. ????}??
    31. ??????
    32. ????public?int?hashCode()?{??
    33. ????????final?int?prime?=?31;??
    34. ????????int?result?=?1;??
    35. ????????result?=?prime?*?result?+?userId;??
    36. ????????return?result;??
    37. ????}??
    38. ??????
    39. ????public?boolean?equals(Object?obj)?{??
    40. ????????if?(this?==?obj)??
    41. ????????????return?true;??
    42. ????????if?(obj?==?null)??
    43. ????????????return?false;??
    44. ????????if?(getClass()?!=?obj.getClass())??
    45. ????????????return?false;??
    46. ????????final?UserModel?other?=?(UserModel)?obj;??
    47. ????????if?(userId?!=?other.userId)??
    48. ????????????return?false;??
    49. ????????return?true;??
    50. ????}?????
    51. }??

    12.2.2??建立条件组合对象

    在查询的时候,通常需要实现用户可以自由组合查询条件的功呢,也就是用户自由组合使用多个查询条件中的一项或某几项。

    比如,在查询用户信息的时候,可以指定如下查询条件:按照用户编号精确查询;按照姓名模糊查询(输入“李”可以查出所有名字中带有“李”字的用户);按性别精确查询;按年龄的范围查询,如15到20之间,或者大于25岁的。

    这些条件用户可能都填了,也可能只填其中的某几项,也可能都不填写。那么在做查询的时候,就要去处理用户填写条件的各种组合情况,并把那些符合所有这些条件的记录查询出来。

    先不要着急想怎么实现组合查询,第一个问题是用一个什么样的对象来存放这样一组条件呢?

    按照上面描述的组合条件,这个对象要包含一个编号(用于精确查询)、一个姓名(用于模糊查询)、一个性别(用于模糊查询)和两个年龄(一个用于存范围的最大值,另一个用于存范围的最小值)。有朋友马上就想到了使用UserModel,但是这里有一个小小的问题,UserModel可以存一个编号、一个姓名、一个性别和一个年龄,可是还少一个年龄属性。

    可以简单的如下来实现,做一个UserQueryModel,让它继承UserModel,在UserQueryModel中只写出UserModel缺少的属性(一个年龄),当然它的名字不能叫age,可以叫做age2,这样在查询的时候就使用UserQueryModel,示例代码如下:

    ?

    java代码:查看复制到剪贴板打印
    1. public?class?UserQueryModel?extends?UserModel?{??
    2. ????private?int?age2;??
    3. ????public?int?getAge2()?{??
    4. ????????return?age2;??
    5. ????}??
    6. ????public?void?setAge2(int?age2)?{??
    7. ????????this.age2?=?age2;??
    8. ????}??
    9. }??

    12.2.3??实现数据层

    使用JDBC作为这次示例的数据层,但是JDBC并不是本书的介绍重点。因此,这里只是简单的给出其实现,如果读者没有JDBC基础,请查阅JDBC的相关资料。

    ?????? 为了实现最终的增删改查的目标,数据层必须实现以下功能:

    • 增:添加一条新的记录。
    • 改:按照主键修改一条已有记录。
    • 删:按照主键删除一条已有记录。
    • 查一条:按照主键查询出一条已有记录。
    • 查全部:查出所有已有记录。
    • 按条件查:按照组合条件查出所有符合条件的记录。

      要实现数据层首先就要获得数据库的连接,这里用的是apache的简单数据源BasicDataSource实现,只需要指定驱动类、数据库的地址、用户名和密码即可,最终返回一个DataSource对象,示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. public?class?DataSourceHolder?{??
      2. ????private?BasicDataSource?ds?=?new?BasicDataSource();??
      3. ???????
      4. ????private?DataSourceHolder(){??
      5. ????????ds.setDriverClassName("org.gjt.mm.mysql.Driver");??
      6. ????????ds.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gb2312");??
      7. ????????ds.setUsername("root");??
      8. ????????ds.setPassword("");??
      9. ????}??
      10. ????private?static?class?SingletonHolder{??
      11. ????????private?static?DataSourceHolder?instance?=?new?DataSourceHolder();??
      12. ????}?????
      13. ????public?static??DataSourceHolder?getInstance(){??
      14. ????????return?SingletonHolder.instance;??
      15. ????}??
      16. ????public??DataSource?getDataSource(){??
      17. ????????return?ds;??
      18. ????}??
      19. }??

      上面的DataSourceHolder实现成了一个单例,这里用的是“Lazy initialization holder class模式”来实现的单例,不了解的朋友可以参见拙著《研磨设计模式》的单例模式一章,或者是参阅其他的相关资料。

      接下来,开始正式实现数据层的各个方法:

      1:实现添加一条新的记录,示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. public?void?create(UserModel?user){??
      2. ????Connection?conn?=?null;??
      3. ????try?{??
      4. ????????conn?=?DataSourceHolder.getInstance().getDataSource().getConnection();??
      5. ????????final?String?sql?=?"insert?into?tbl_user(userId,name,sex,age)?values(?,?,?,?)";??
      6. ????????PreparedStatement?ps?=?conn.prepareStatement(sql);??
      7. ????????int?count?=?1;??
      8. ????????ps.setInt(count++,?user.getUserId());??
      9. ????????ps.setString(count++,?user.getName());??
      10. ????????ps.setString(count++,?user.getSex());??
      11. ????????ps.setInt(count++,?user.getAge());??
      12. ????????ps.execute();??
      13. ??????????
      14. ????????ps.close();??
      15. ????}?catch?(Exception?e)?{??
      16. ????????e.printStackTrace();??
      17. ????}?finally?{??
      18. ????????try?{??
      19. ????????????conn.close();??
      20. ????????}?catch?(SQLException?e)?{??
      21. ????????????e.printStackTrace();??
      22. ????????}??
      23. ????}?????????
      24. }??

      2:实现按照主键修改一条已有记录,示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. public?void?update(UserModel?user){??
      2. ????Connection?conn?=?null;??
      3. ????try?{??
      4. ????????conn?=?DataSourceHolder.getInstance().getDataSource().getConnection();??
      5. ????????final?String?sql?=?"update?tbl_user?set?name=?,sex=?,age=??where?userId=?";??
      6. ????????PreparedStatement?ps?=?conn.prepareStatement(sql);??
      7. ????????int?count?=?1;??
      8. ????????ps.setString(count++,?user.getName());??
      9. ????????ps.setString(count++,?user.getSex());??
      10. ????????ps.setInt(count++,?user.getAge());??
      11. ????????ps.setInt(count++,?user.getUserId());??
      12. ????????ps.execute();??
      13. ??????????
      14. ????????ps.close();??
      15. ????}?catch?(Exception?e)?{??
      16. ????????e.printStackTrace();??
      17. ????}?finally?{??
      18. ????????try?{??
      19. ????????????conn.close();??
      20. ????????}?catch?(SQLException?e)?{??
      21. ????????????e.printStackTrace();??
      22. ????????}??
      23. ????}?????????
      24. }??

      3:实现按照主键删除一条已有记录,示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. public?void?delete(int?userId){??
      2. ????Connection?conn?=?null;??
      3. ????try?{??
      4. ????????conn?=?DataSourceHolder.getInstance().getDataSource().getConnection();??
      5. ????????final?String?sql?=?"delete?from?tbl_user?where?userId=?";??
      6. ????????PreparedStatement?ps?=?conn.prepareStatement(sql);??
      7. ????????ps.setInt(1,?userId);??
      8. ????????ps.execute();??
      9. ??????????
      10. ????????ps.close();??
      11. ????}?catch?(Exception?e)?{??
      12. ????????e.printStackTrace();??
      13. ????}?finally?{??
      14. ????????try?{??
      15. ????????????conn.close();??
      16. ????????}?catch?(SQLException?e)?{??
      17. ????????????e.printStackTrace();??
      18. ????????}??
      19. ????}?????????
      20. }??

      4:事先按照主键查询出一条已有记录的功能,示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. public?UserModel?getSingle(int?userId){??
      2. ????UserModel?user?=?null;??
      3. ????Connection?conn?=?null;??
      4. ????try?{??
      5. ????????conn?=?DataSourceHolder.getInstance().getDataSource().getConnection();??
      6. ????????final?String?sql?=?"select?*?from?tbl_user?where?userId=?";??
      7. ????????PreparedStatement?ps?=?conn.prepareStatement(sql);??
      8. ????????ps.setInt(1,?userId);??
      9. ????????ResultSet?rs?=?ps.executeQuery();??
      10. ????????if(rs.next()){??
      11. ????????????user?=?this.rs2model(rs);??
      12. ????????}??
      13. ??????????
      14. ????????rs.close();??
      15. ????????ps.close();??
      16. ????}?catch?(Exception?e)?{??
      17. ????????e.printStackTrace();??
      18. ????}?finally?{??
      19. ????????try?{??
      20. ????????????conn.close();??
      21. ????????}?catch?(SQLException?e)?{??
      22. ????????????e.printStackTrace();??
      23. ????????}??
      24. ????}?????????
      25. ????return?user;??
      26. }??
      27. private?UserModel?rs2model(ResultSet?rs)?throws?Exception{??
      28. ????UserModel?user?=?new?UserModel();??
      29. ????user.setUserId(rs.getInt("userId"));??
      30. ????user.setName(rs.getString("name"));??
      31. ????user.setSex(rs.getString("sex"));??
      32. ????user.setAge(rs.getInt("age"));??
      33. ????return?user;??
      34. }??

      在里面实现了一个私有方法rs2model,用来把从数据库获取的一条记录,转换成为一个UserModel的对象。这是个多个方法公用的方法,因此把这些公共的功能提出来实现成为私有方法。

      5:实现查出所有已有记录的功能,示例如下:

      ?

      java代码:查看复制到剪贴板打印
      1. public?List<UserModel>?getAll(){??
      2. ????List<UserModel>?list?=?new?ArrayList<UserModel>();??
      3. ????Connection?conn?=?null;??
      4. ????try?{??
      5. ????????conn?=?DataSourceHolder.getInstance().getDataSource().getConnection();??
      6. ????????final?String?sql?=?"select?*?from?tbl_user?order?by?userId";??
      7. ????????PreparedStatement?ps?=?conn.prepareStatement(sql);??
      8. ????????ResultSet?rs?=?ps.executeQuery();??
      9. ????????while?(rs.next()){??
      10. ????????????UserModel?user?=?this.rs2model(?rs);??
      11. ????????????list.add(user);??
      12. ????????}??
      13. ??????????
      14. ????????rs.close();??
      15. ????????ps.close();??
      16. ????}?catch?(Exception?e)?{??
      17. ????????e.printStackTrace();??
      18. ????}?finally?{??
      19. ????????try?{??
      20. ????????????conn.close();??
      21. ????????}?catch?(SQLException?e)?{??
      22. ????????????e.printStackTrace();??
      23. ????????}??
      24. ????}?????????
      25. ????return?list;??
      26. }??

      6:实现按照组合条件查出所有符合条件的记录。实现这个功能会稍微麻烦一点,首要的问题就是用户输入的条件是不确定的,因此查询用的sql也就不能确定了,那么怎么实现呢?

      方法是动态的拼接sql,根据用户输入的条件来拼接sql,如果用户输入了某个条件值,那么就在sql上拼接该条件,如果用户没有输入,那么就不用在sql上拼接这个条件。具体的实现请参看generateWhere方法。示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. /**?
      2. ?*?根据UserQueryModel中的数据情况动态生成对应的条件语句?
      3. ?*?@param?uqm?封装查询条件数据的模型?
      4. ?*?@return?按照查询条件数据来动态生成的条件语句?
      5. ?*/??
      6. private?String?generateWhere(UserQueryModel?uqm){??
      7. ????StringBuffer?buffer?=?new?StringBuffer();??
      8. ????//用户是否选用用户编号作为条件??
      9. ????if?(uqm.getUserId()>0){??
      10. ????????buffer.append("?and?userId?=??");??
      11. ????}??
      12. ????//用户是否选用用户姓名作为条件??
      13. ????if?(uqm.getName()!=null&&uqm.getName().trim().length()>0){??
      14. ????????buffer.append("?and?name?like??");??
      15. ????}??
      16. ????//用户是否选用性别作为条件??
      17. ????if?(uqm.getSex()!=null&&uqm.getSex().trim().length()>0){??
      18. ????????buffer.append("?and?sex?=??");??
      19. ????}??
      20. ????//用户是否选用年龄范围最小值作为条件??
      21. ????if?(uqm.getAge()>0){??
      22. ????????buffer.append("?and?age?>=??");??
      23. ????}??
      24. ????//用户是否选用年龄范围最大值作为条件??
      25. ????if?(uqm.getAge2()>0){??
      26. ????????buffer.append("?and?age?<=??");??
      27. ????}??
      28. ????return?buffer.toString();??
      29. }??

      另外一个问题,由于sql是动态拼接出来的,那么向sql传入参数的过程也不能固定,同样按照动态拼接sql的方式,来动态的设置sql的参数。具体的实现请参看preparePs方法。示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. /**?
      2. ?*?向sql语句中的"?"?设置参数值?
      3. ?*?@param?uqm?封装查询条件数据的模型?
      4. ?*?@param?ps?PreparedStatement?对象?
      5. ?*/??
      6. private?void?preparePs(UserQueryModel?uqm,PreparedStatement?ps)?throws?SQLException{??
      7. ????int?count?=?1;??
      8. ????if?(uqm.getUserId()>0){??
      9. ????????ps.setInt(count++,?uqm.getUserId());??
      10. ????}??
      11. ????if?(uqm.getName()!=null&&uqm.getName().trim().length()>0){??
      12. ????????ps.setString(count++,?"%"+uqm.getName()+"%");??
      13. ????}??
      14. ????if?(uqm.getSex()!=null&&uqm.getSex().trim().length()>0){??
      15. ????????ps.setString(count++,?uqm.getSex());??
      16. ????}??
      17. ????if?(uqm.getAge()>0){??
      18. ????????ps.setInt(count++,?uqm.getAge());??
      19. ????}??
      20. ????if?(uqm.getAge2()>0){??
      21. ????????ps.setInt(count++,?uqm.getAge2());??
      22. ????}??
      23. }??

      再来看看按条件查询功能的实现,示例代码如下:

      ?

      java代码:查看复制到剪贴板打印
      1. public?List<UserModel>?getByCondition(UserQueryModel?uqm){??
      2. ????List<UserModel>?list?=?new?ArrayList<UserModel>();??
      3. ????Connection?conn?=?null;??
      4. ??????
      5. ????try?{??
      6. ????????conn?=?DataSourceHolder.getInstance().getDataSource().getConnection();??
      7. ????????//调用前面定义的生成where语句的方法??
      8. ???????????//由于不知道UserQueryModel中属性值的情况??
      9. ???????????//所以必须在sql语句的主题中添上恒成立条件1=1??
      10. ????????final?String?sql?=?"select?*?from?tbl_user?where?1=1?"?+?this.generateWhere(uqm)?+?"?order?by?userId";??
      11. ????????PreparedStatement?ps?=?conn.prepareStatement(sql);??
      12. ????????//调用前面定义的向PrepareStatment赋值的方法??
      13. ????????this.preparePs(uqm,?ps);??
      14. ????????ResultSet?rs?=?ps.executeQuery();??
      15. ????????while?(rs.next()){??
      16. ????????????UserModel?user?=?this.rs2model(rs);??
      17. ????????????list.add(user);??
      18. ????????}??
      19. ????????rs.close();??
      20. ????????ps.close();??
      21. ????}?catch?(Exception?e)?{??
      22. ????????e.printStackTrace();??
      23. ????}?finally?{??
      24. ????????try?{??
      25. ????????????conn.close();??
      26. ????????}?catch?(SQLException?e)?{??
      27. ????????????e.printStackTrace();??
      28. ????????}??
      29. ????}??
      30. ????return?list;??
      31. }??

      ?

      私塾在线网站原创《研磨struts2》系列

      转自请注明出处:【http://sishuok.com/forum/blogPost/list/0/4101.html】

      欢迎访问http://sishuok.com获取更多内容

热点排行