逃避失敗的同時,也躲開了成功!
有時候有些人總在高調的宣講,自己是多么的高明,但是咱們做業務系統的,再怎么牛,最后還不是對數據的增刪改查嗎。無論使用多復雜的技術,我們這些人也逃脫不了數據的干系。編程猶如生活,生活就像強奸,如果不可避免,就享受吧。
我相信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);
這樣一句代碼就搞定的刪除功能,還有必要拆到不同的層嗎?
好吧,該說的都說完了。就是這么簡單。
最近剛剛離職,開始要尋找新的飯碗了,可能暫時不能更新了。