逃避失败的同时,也躲开了成功!
有时候有些人总在高调的宣讲,自己是多么的高明,但是咱们做业务系统的,再怎么牛,最后还不是对数据的增删改查吗。无论使用多复杂的技术,我们这些人也逃脱不了数据的干系。编程犹如生活,生活就像强奸,如果不可避免,就享受吧。
我相信CRUD的概念尽人皆知,老少咸宜。甚至有一天一个很高手的家伙鄙视我,说:你们这些家伙,整天就是CRUD,有什么技术。这个问题就像我们农民种地一样,耕地播种,貌似一点技术含量都没有,但是有的收成好,有的就收成不好,收成最好的当属袁隆平了。正所谓道不同不相为谋,谁说CRUD不可以很优雅呢。下面我们来简单的说一下LML中简单优雅的CRUD。
在当下很多企业(很多是作坊)中,一直对框架进行大量的设计,分层貌似是最被大量运用的技术。这可能是在响应界面和逻辑分离的号召,但是我们怎么能够严格的区分界面或者逻辑呢。假如吧,界面中没有逻辑,那是不是数据都没法展现了?不好意思,我伤到谁的心了。接触.net的估计都知道微软的实例项目petshop,一看那么一堆东西,很强大。但是,我们这样的小团队真的需要嘛?我的亲身经历是不需要,我们要的就是简单,就是快速。
下面给出完整代码:
package LML.Action.Article; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; import java.util.UUID; import LML.Core.Helper.DBHelper; import LML.Core.Helper.StringHelper; import LML.Core.System.Area; import LML.Core.System.Helper; import LML.Core.System.PageBaseAction; import LML.Core.System.Pager; import LML.Core.System.SkipCheckPower; import LML.Core.System.SysMenu; import LML.Core.System.SysPower; import LML.Model.Diary; @Area("Article") @SkipCheckPower() @Helper({DBHelper.class,StringHelper.class}) public class DiaryAction extends PageBaseAction{ private String title; public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } private String id; private Diary diary; public String getId() { return id; } public void setId(String id) { this.id = id; } public Diary getDiary() { return diary; } public void setDiary(Diary diary) { this.diary = diary; } @SysMenu(MenuId="DiaryList",MenuName="日志列表",MenuPic="",MenuParent="Article",MenuLevel=2,MenuSort=1) @SysPower(PowerId="DiaryListPower",PowerMenu="DiaryList",PowerName="日志列表查看") public String List() { try { Pager pager=DBHelper.ShowPager(pageSize, page, "* ", " diary ", strWhere(), " order by pubTime desc"); setPager(pager); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return SUCCESS; } private String strWhere() { String strWhere=""; System.out.print("title"+title); if(title!=null&&!title.isEmpty()) { strWhere=" where title like '%"+ParamValue("title",title,true)+"%'";; } return strWhere; } public String Edit() { if(id!=null&&!id.equals("")) { Diary diary=(Diary) DBHelper.Find(Diary.class, id); System.out.print("diary"+diary.getDiaryContent()); setDiary(diary); } return SUCCESS; } public String Save() { try { java.util.Date date=new java.util.Date(); Timestamp tt=new Timestamp(date.getTime()); diary.setPubTime(tt); if(diary.getId()==null||diary.getId().equals("")) { diary.setId(UUID.randomUUID().toString()); DBHelper.Create(StringHelper.ModelHtmlEncode(diary)); } else { DBHelper.Update(StringHelper.ModelHtmlEncode(diary)); } } catch(Exception ex) { ex.printStackTrace(); } return JavaScript("alert('保存成功!');parent.location.href='Diary_List.action'"); } public String Delete() { try { if(id!=null&&!id.equals("")) { DBHelper.Delete(Diary.class, id); } } catch(Exception ex) { ex.printStackTrace(); } return JavaScript("alert('删除成功!');parent.location.href='Diary_List.action'"); } }
#set($layout="default_Pager.html") <form id="form1" name="form1" action="?"> <div class="articles"> <div class="clear tabtext"> <!--style="display:none;"--> <div class="tab1" style="display:none;"> <!--查询条件模块开始--> <div class="admin_search"> <div class="admin_search_top"> <span>查询方式</span></div> <div class="admin_search_contant"> <div class="admin_search_contant_left"> <span>标题:</span><input name="title" value="$!title"/> </div> <div class="admin_search_contant_right"> <table border="0" cellspacing="0" cellpadding="0" class="right" onclick="DoSearch();"> <tr> <td class="search_button bt1"> <a>查询</a> </td> <td class="search_button_right" style="cursor:pointer"> </td> </tr> </table> </div> <div class="clear"></div> </div> </div> <!--查询条件模块结束--> <div class="table_name"> <div class="table_name_left"><img src="/Theme/1/base/images/dian1.png" /><span>日志管理</span></div> <div class="table_name_right"> <div class="admin_page_left"> <ul> <li> <table border="0" cellspacing="0" cellpadding="0" onclick="DptStateSetMore('D');"> <tr> <td class="admin_page_left_left btn3"> <a>删除</a> </td> <td class="admin_page_left_right"></td> </tr> </table> </li> <li> <table border="0" cellspacing="0" cellpadding="0" onclick="location.href='Diary_Edit.action'"> <tr> <td class="admin_page_left_left btn3"> <a>新增</a> </td> <td class="admin_page_left_right"></td> </tr> </table> </li> </ul> </div> </div> </div> <!--表格列表开始--> <table width="100%" border="0" cellspacing="0" cellpadding="0" class="table" name="table" id="table"> <tr> <th width="6%"> <input type="checkbox" id="checkAll" name="checkAll"/> </th> <th width="50%"> 日志标题 </th> <th width="20%"> 发表时间 </th> <th width="30%"> 操作 </th> </tr> #if($pager.result.rowCount==0) <tr> <td colspan="4" align="center" style="color: Red; font-weight: bold;"> 暂无记录 </td> </tr> #else #foreach($item in $pager.result.rows) <tr> <td> <input type="checkbox" /> </td> <td class="left_tab" title="$!item.title"> $!item.title </td> <td> $!item.pubTime </td> <td class="table_operating"> <a href="Diary_Edit.action?id=$!item.id"> <img src="../Theme/1/base/images/edit/image45.png" />编辑</a> <a href="Diary_Delete.action?id=$!item.id" target="iframe_data"> <img src="../Theme/1/base/images/edit/image45.png" />删除</a> </td> </tr> #end #end </table> </div> </div> </div> </form> <script type="text/javascript"> jQuery(function () { //回车就能触发验证提交表单 $(document).keydown(function (e) { var code = e.keyCode; if (code == 13 && e.target.id != "Dis_PageSize") { DoSearch(); } }); }); //查询提交form function DoSearch() { jQuery("#form1").submit(); } </script>
#set($layout="default_Edit.html") <script type="text/javascript"> $(document).ready(function () { jQuery.formValidator.initConfig({ formID: "formSave", theme: "ArrowSolidBox", debug: false, submitOnce: false, onError: function (msg, obj, errorlist) { alert(msg); }, onShowClass: "", onFocusClass: "", onCorrectClass: "" }); }); </script> <div class="articles"> <div class="clear tabtext"> <div class="tab1" style="display:none;"> <!--内容开始--> <div class="admin_main_top1"><img src="../Theme/1/base/images/dian1.png" /><span>日志编辑</span></div> <!--表格列表开始--> <form id="formSave" action="Diary_Save.action" method="post" target="iframe_data"> <input type="hidden" name="diary.id" value="$!diary.id"/> <table width="100%" border="0" cellspacing="0" cellpadding="0" class="table" name="table" > <tr> <td width="10%" class="right_tab"><span style="color:Red">*</span>日志标题:</td> <td width="90%" class="left_tab"><input type="text" name="diary.title" id="title" value="$!diary.title" maxlength="20"/></td> </tr> <tr> <td width="10%" class="right_tab">日志内容:</td> <td width="90%" class="left_tab"><textarea name="diary.diaryContent" id="diaryContent" maxlength="60">$!diary.diaryContent</textarea><br /> </tr> <tr> <td class="right_tab"></td> <td class="left_tab"> <table border="0" cellspacing="0" cellpadding="0" class="table_no" onclick="ok()"> <tr> <td class="search_button bt1"><a href="#" >确定</a> </td> <td class="search_button_right"> </td> </tr> </table> <table border="0" cellspacing="0" cellpadding="0" class="table_no admin_10" onclick="javascript:history.back();"> <tr> <td class="search_button bt1"><a href="javascript:history.back();">取消</a></td> <td class="search_button_right"> </td> </tr> </table> </td> </tr> </table> </form> <!--表格列表开始--> <!--内容结束--> </div> </div> </div> <script type="text/javascript"> jQuery(function () { var editor = CKEDITOR.replace('diaryContent'); CKFinder.setupCKEditor(editor, 'http://www.cnblogs.com/Content/ckeditor/ckfinder'); }) function ok() { jQuery("#diaryContent").val(CKEDITOR.instances.diaryContent.document.getBody().getText()); $("#formSave").submit(); } </script>
注释:
1, C
C reate new records
首先声明一下,我们的新增页面和修改页面是同一个页面,目前大部分框架都应该支持这么做,简单又易于维护。我们这里一般叫Edit。Edit一般会用到一个记录主键,根据是否传递主键参数决定是否需要查询数据库:
if(id!=null&&!id.equals(""))
{
Diary diary=(Diary) DBHelper.Find(Diary.class, id);
setDiary(diary);
}
当然了,如果查询到的记录,该记录就会绑定到页面上,形成编辑界面,否则就是新增界面。
Edit界面存在一个form,就如同所有的框架一样,没有什么区别,一般我们form对应的Action=”Save.action”,这样便可以将参数提交到SAVE Action,而且我们还可以使用Struts的自动绑定技术。
if(diary.getId()==null||diary.getId().equals(""))
{
diary.setId(UUID.randomUUID().toString());
DBHelper.Create(StringHelper.ModelHtmlEncode(diary));
}
else
{
DBHelper.Update(StringHelper.ModelHtmlEncode(diary));
}
我们的代码写的是非常简单,没有经过N层,也没考虑所谓的更换数据库的需求。
2, R
R etrieve existing records
很郁闷的是,有一些框架之中在这里还需要程序员浪费很多时间。我们为了一个查询,还需要新建处理一个或者多个ViewModel,我觉得这样不快速也不方便维护,总觉得和MVC的初衷有一点点的违背。我们为什么要使用MVC,原因之一就是开发快速易于维护,然而我们为了追求这一M的概念,又引入了ViewModel,在数据库中随处可见”View”,这样有点过头了吧。不如,我们使用最原始的sql查询,快速又方便。而且很明显,LML对分页和查询也进行了比较严格的封装,完全没有必要再让每一个程序员分别针对不同的功能再实现不同的分页逻辑。我不是在胡扯,曾经接触过一个.net Mvc框架就要针对不同的模块实现不同的分页逻辑,而且需要跨越N层。
3, U
U pdate existing records
同C。
4, D
D elete existing records.
DBHelper.Delete(Diary.class, id);
这样一句代码就搞定的删除功能,还有必要拆到不同的层吗?
好吧,该说的都说完了。就是这么简单。
最近刚刚离职,开始要寻找新的饭碗了,可能暂时不能更新了。