开发者社区> 问答> 正文

关于activerecord的model增加属性的问题

如下描述正确与否,哪里有纰漏的,@詹兄请指出。

关于activerecord的model属性的创建:

jfinal activerecord的model使用map存储属性值,这与传统的model(javabean)的设计是不一样的,在ActiveRecordPlugin实例化并.start()后TableInfoBuilder.buildTableInfo(tableMappings)即将数据库中数据表及字段的信息创建好已备使用,此时比如demo的数据表blog,其对应的model为Blog,blog的属性(存储在map中)有id,title,content三个,这三个属性是由TableInfoBuilder.buildTableInfo(tableMappings)完成填入Blog中的。

关于model属性的读取:

Java读取:

List<Blog> blogList = Blog.dao.find("select * from blog order by id asc");
 for(Blog blog : blogList){
    //Get attribute of mysql type: int, integer, tinyint, smallint, mediumint
    blog.getInt("id");  // 取Integer,而非int
    // Get attribute of mysql type: varchar, char, enum, set, text, tinytext, mediumtext, longtext
    blog.getStr("title");   
 }

这里提一个建议,@詹兄,考虑将getInt方法改名为getInteger,getStr改名为getString。

FreeMaker读取:

<#list blogList as x>
 <tr>
  <td style="text-align:left;">${x.id}</td>
  <td style="text-align:left;">${(x.addColumn)!}</td>
  <td style="text-align:left;">${x.title}</td>
 </tr>
 </#list>

这里有一个问题FreeMake默认对null值不做处理,如果某个值为null,则会发生异常,处理方法是${value!}即在值后加一个英文感叹号,此时会将null当空字符处理。

如何给model添加额外的属性:

再以blog为例,开发中对model的需求,可能需要增加额外的属性,经詹兄的指导及实践,jfinal有如下两种或四种model添加额外属性的方法。

方法一(此种方法添加的额外属性,是即时的(下一次find的List没有put属性addColumn,Blog即没有属性addColumn)?):

public void list() {
   List<Blog> blogList = Blog.dao.find("select * from blog order by id asc");
   for(Blog blog : blogList){
    // 覆盖属性原来的值,这里注意对于表字段映射的属性,使用put或set的效果是一样的
    blog.put("title", "11");
    // 而对于非表字段映射的属性,则不可以set,否则会出现异常,找不到属性
    blog.put("addColumn", blog.getInt("id")+10);
   }
   setAttr("blogList", blogList);
   render("blog.html");
  }
 

方法二(即传统javabean的做法):

private Integer addColumn;
   
  public Integer getAddColumn() {
   return this.addColumn;
  }
 
 public void setAddColumn(Integer addColumn) {
   this.addColumn = addColumn;
  }

这两种添加额外属性方法,对于FreeMaker而言,取数据的方法都是一样的model.property。

顺便提一句,经测试,如果这两种方法一起使用,FreeMaker取数据model.property取的是 getAddColumn() 而非方法一put的值,这里值得注意。

方法三(亦或方法三及四,或者方法一二的混合使用,参看如下代码):

Mode的代码:

private Integer addColumn;
   
  public Integer getAddColumn() {
   this.addColumn = get("addColumn");  //注意此行
   return this.addColumn;
  }
 
 public void setAddColumn(Integer addColumn) {
   put("addColumn", addColumn);
  }

赋值部分代码:

bog.put("addColumn", blog.getInt("id")+15);   //方法三
 bog.setAddColumn(blog.getInt("id")+15);   //方法四,如果可以这么说

总结:关于model添加额外属性,个人建议使用方法二,因为方法一、三、四,容易与数据表原有属性的操作混淆。

展开
收起
小旋风柴进 2016-06-07 15:46:49 2698 0
1 条回答
写回答
取消 提交回答
  • 首先,谢谢你的这些建议,这位同学的确是发现了一些细节,如下我逐一说一下:

    1:考虑将方法名 getInt 改为 getInterger,getStr改为getString

     当初的确是这么设计的,后来为了省代码,所以没这么干了,因为getInt与getStr是比较长用的方法。JFinal的设计目标是开发效率高,代码量省,所以很多地方都体现这个设计原则。
    

    2:Model 尽量去使用 set 方法

     Model的set方法能保证属性确实是存在的,是正确的,以免开发的过程中出现手误,出现手误时能在开发过程中及早发现错误。出现手误可以造成手误过的属性不能入库,而开发者认为应该入库,实质是手误导致问题发生。而有时候需要在model 中存放并不存在的属性值,此时可以使用put方法,很是方便。
    

    3:如何给Model添加额外的属性

    为了节省代码,就算要给Model添加额外属性时,也不必定义新的成员变量,只需要创建getter与setter方法即可,在getter与setter方法中去存取父类中的map即可,当然或许要对null值以及默认值时进行一些额外处理。

    4:FreeMarker表达式 ${model.property}取值问题

    如果model中存在property,并且存在 getProperty()方法时,FreeMarker会以 getProperty()优先,其实这也不能完全确定,例如在FreeMarker中迭代时,如果最开始碰到的是无getXxxx方法的property,那么,以后面的迭代中可能就一直使用map中的property。这个以前测试过,现在有些忘记了。这个问题实质与JFinal无关,完一是FreeMarker的个人行为 :)
    2019-07-17 19:30:21
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载