随笔-10  评论-22  文章-1  trackbacks-0
  2009年10月16日
Annotation是JavaSE5开始引入的,在Java的世界已是大行其道,各大开源框架Hibernate、Spring等都对它无缝集成,足见其份量了。。
其实很早就出现在程序员的视野,只是关注的比较少:@Override、@SuppressWarnings("unchecked"),开始主要觉得没什么用处,后来公司的框架用到它,感觉还不错。。于是来一记:

在网上搜Annotation的学习资料不是很多,还是用的人不多,比较经典的入门就是这个:实战篇:设计自己的Annotation,很清楚,通俗易懂,这里我就不赘述了。然而仅仅是弄懂它是怎么回事,具体还是没什么用处,这也是大多数开发人员的感觉。

在现在的公司的经历两次框架升级,第一次没有用到Annotation,xml配置文件大行其道:Action跳转、Ibatis sqlmapper、Form表单(我们的表单都是从后台生成的),整个项目xml眼花缭乱,每个模块都有自己专属的配置文件,然后集中到一起处理,而我们最痛苦的莫过于写那大量重复的配置文件。

后来公司接了个ERP的单子,技术总监马上意识到框架该升级了,他技术很牛,我们公司的框架就是他一人写的,两周之后,新框架出炉,xml只保留三分之一:Action跳转、Form表单都不再使用xml配置,而是Annotation横空出世,给我的感觉:它就像一个救世主,让我们的框架重生,它就是这次升级的最大亮点,只有sqlmapper依然保留,这无可厚非,因为它原本是ibatis封装的,Action控制器既不是Struts1,Struts2,也不是Webwork,是总监自己封装的Servlet,Form表单都由后台生成js组件抛到前端,通过反编译看到源码,其实还是很基础的,贴些代码上来看下吧:

1.Action请求部分:
    /**
     * 显示新增页面
     * author YuWenLin
     * date 2010-5-13 上午10:31:57
     * 
@param data
     
*/
    @Action(
"/add.shtml")
    @Permission(
"client.ContractType.add")
    
public void add(ActionData data){
        FormBuilder builder 
= data.getService(FormBuilder.class);
        builder.append(Type.
class);
        builder.setAction(
"client/contract/type/add.do");
        data.put(
"script", builder);
        
//向页面抛出cookie提示信息
        MessageUtil.putMessage(data);
        data.setResulter(
"template");
        data.setPath(
"client/contract/type/type.shtml");
    }
可能大家看得不太明白(每个公司都有自己框架),没有关系,就两句:
@Action("/add.shtml")
它就是负责请求显示新增的页面,就这一句,不需要像我们以前的action.xml(类似Struts2的跳转),干净利索吧,当然底层后台有处理,但是公共的,不需我们管,至于
@Permission("client.ContractType.add")
就是用来处理权限管理的,也是Annotation的使用,就这一句。就权限管理,后面我也会记述。。。

2.再来看看@Action底层的定义:
package org.plugbase.action;

import java.lang.annotation.Annotation;

public interface Action
    
extends Annotation
{

    
public abstract String value();
}
说明下:extends Annotation跟 @interface是一样的效果,只不过前者手动extends,后者自动的。
怎么样,很基础吧,跟jdk源码是一样的。。。

3.JavaBean生成表单:
    @Widget(value="TextBox")
    @Valider({
"notempty","len(2,8)"})
    
public void setName(String name) {
        
this.name = name;
    }
给setter方法加Annotation,@Widget是组件,@Valider是验证
意思就是给name字段生成TextBox组件,并做验证处理,后台有相应的公共js组件,验证控件库调用,我们所有的表单组件都是这样生成的,说实话,这样生成一个页面真有点繁锁,既要写js,又要写后台,前端还要配,还真是有技术含量,呵呵。。。但是它保证一致性,所有表单组件,验证控件,如TextBox我们只有一套,所有人都去调用这一套,不得再重造,因为它是框架。。。

4.@Widget底层定义:
import java.lang.annotation.Annotation;

public interface Widget
    
extends Annotation
{

    
public abstract String value();

    
public abstract String defaultValue();

    
public abstract String dataType();

    
public abstract String dataSource();
}
@Valider类似,当然这些都只是定义、声明,具体怎么用,这里就不贴了,毕竟是人家东西嘛

怎么样,看到这些,似乎觉得Annotation开始起作用了,其实我一直觉得,Annotation就是为xml所生,因为它们俩是死对头,不管单一地用谁,都有缺陷,
只有结合才是完善,正所谓,没有最好,只有更好,合理就行。

在这里我可能没有贴出什么@Annotation技术含量的东西,但是我想要表达的是一种思想,一种框架的思想,并不是什么地方都能用到Annotation,一般的中小型项目根本没必要用它,因为xml就搞定,所以用在需要用的地方,将它的能量发挥到最大。。。

以上仅为一家之言,欢迎拍砖。。。

posted @ 2010-08-10 16:47 独孤行 阅读(1699) | 评论 (1)编辑 收藏
     摘要: 在项目中使用ibatis有一段时间了,之前一直用jdbc、hibernate。自我感觉ibatis是介于jdbc和hibernate之间的非常实用的轻量级框架,相信用过的人都有同感吧。对搞java的来说,上手是非常快的,只要你具备sql基础,再加一点ORM的思想,夏昕的《ibatis开发指南》是不错的选择。 今天项目搞完了,我就把所学的,以及在项目中用到拿来贴一番,也是对我个人技术的总结吧,怎样...  阅读全文
posted @ 2010-04-01 11:35 独孤行 阅读(3344) | 评论 (0)编辑 收藏
thickbox是jQuery的一个插件,其作用是弹出对话框、网页框,使用户体验度更加愉悦,下面就来简单介绍它的几种用法。
声明一下:这只是个人的总结记载而已。
准备工作:你需要三个文件:thickbox.js、thickbox.css、jquery.js,网上到处可下
具体使用:
第一步:将这三个文件引入到你要使用thickbox的页面
<script type="text/javascript" src="jquery.js"></script> 
    
<script type="text/javascript" src="thickbox.js"></script>
    
<link rel="stylesheet" href="thickbox.css" type="text/css" />
第二步:一般简单使用就是给<a>标签和Button添加样式:class=thickbox
还有就是通过thickbox函数调用:如tb_init()、tb_show();见下文。
几种不同用法:
1.点击显示图片:
 <a href="001.jpg" class="thickbox"><img src="001.jpg"/></a>
ok,就这样搞定
2.点击按钮或链接:
<input alt="#TB_inline?height=300&width=400&inlineId=div1" title="shawnliu" class="thickbox" type="button" value="Show" />   
   
<a href="#TB_inline?height=155&width=300&inlineId=div2&modal=true" class="thickbox">Show hidden modal content.</a>
   
   
<div id="div1" style="display:none">
   
<P>
     这是一个非模式对话框。
   
</P>
   
</div>

   
<div id="div2" style="display:none">
   
<P>
     这是一个模式对话框。
     
<p style="TEXT-ALIGN: center"><INPUT id="Login" onclick="tb_remove()" type="submit" value="  Ok  " /></p>
   
</P>
   
</div>
说明:给你要使用thickbox的<a>或button添加"#TB_inline?height=300&width=400&",#TB_inline是thickbox固定用法,height和width是显示弹出对话框的大小参数,inlineId是你要显示的标签或组件,modal是模式与非模式的选择,当然你还可以接很多你自定义的参数
3.一般在项目中用得比较多的就是加载form的页面,如添加,编辑在同一个list列表页面,这时我们就可以将添加和编辑都做成thickbox形式,如下图:

怎样做呢一样的,给添加链接加thickbox样式:
<a href="add.shtml?width=300&height=250" class="thickbox">新增</a>
前提是你得将要显示的页面(add.shtml)做好,然后指定你要显示的大小
编辑同样是一样:先将原信息提取出来,再让用户修改:

代码也一样:
<a href="edit.shtml?width=300&height=250&nid=item.nid" class="thickbox">编辑</a>
4.能自己定位到需要用thickbox的元素,不使用样式,可以用函数,如:
<div id="PicList">
<a href="Pic01.jpg"><img src="Pic01s.jpg" border="0"/></a>
<a href="Pic02.jpg"><img src="Pic01s.jpg" border="0"/></a>
</div>

$(function() {
tb_init(
"#PicList a[img]");});
5.通过ajax加载的页面,thickbox样式会失效,解决办法:
只要在AJAX载入HTML并更新到页面后执行下以下代码:
tb_init('.thickbox');
6.自定义函数调用:
如点击缩图,要显示大图,缩略图URL只不过在大图URL的后缀前加了s:
<div id="PicList">
<img src="Pic01s.jpg" border="0"/>
<img src="Pic01s.jpg" border="0"/>
</div>

$(function() {
$(
"#PicList img").click(function() {
tb_show(
"",this.src.substring(0,this.src.length-5)+'.jpg',false);
});});
另外,如果想用其它事件,还可以将click改成你想触发thickbox的事件。
下班勒,大概记录到这,以后再加吧。。。


posted @ 2010-03-26 17:47 独孤行 阅读(4628) | 评论 (2)编辑 收藏

在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据UML语言,关系是有方向的。下面以客户(Customer)和订单(Order)的关系为例,阐述一下ORM的中的一对多映射:
我们知道,在关系数据库中,只存在外键参照关系,而且总是由“many”方参照“one“方。
1.建立多对一单向关联——Order(many)--->Customer(one):
-------------------------------Order.java--------------------------------

pack mypack;
import java.io.Serializable;
public class Order implements Serializable{
   
private int id;
   
private String orderNumber;
   
private Customer customer;
   
   
//构造方法及set方法get方法
   
}
在以上代码中customer属性要使用<many-to-one>来映射:
多对一单向关联(many方)
<many-to-one>
    name 
= "customer"   --待映射的持久化类属性名
    column 
= "customer_Id"  --数据库外键字段
    
class = "mypack.Customer"  --持久化类
    not
-null = "true"/>
a.  <many-to-one>的not-null属性 
not-null属性会影响Hiberntae的运行时行为,Hibernate在保存Order对象时,会先检查它的customer属性是否为null:
若为null:在执行session.save(Order)时会抛出PropertyValueException异常;
原因很简单:既然Customer为null,那么对应的外键Customer_Id也为null,试问外键都没有,Order表的数据能插得进去吗
若将not-null 属性设为false:表示外键引用可以为null,试想一下,数据库数据可以插进去吗?
我们来看:在执行session.save(Order)时,发出了sql语句:insert into......
但是当Hibernate自动清理(flush)缓存时,抛出新的异常:TransientObjectException
所谓清理是提交事务或手动Flush,将session与数据库保持同步,很显然不可能同步嘛,Order对象虽然持久化,但Customer没有.
    注:是否应该把<many-to-one>的not-null属性设为true,这根据实际业务而定。通常,订单总是由客户自己发出,因此建议设为true.
b.  级联保存与更新
默认情况下,Hibernate持久化一个对象,不会自动持久化所关联的其它临时对象,因此会有TransientObjectException,
想它关联也可以,<many-to-one>中加个属性cascade="save-update"即可.

2.建立一对多关联——Customer(one)--->Order(many):
-----------------------------Customer.java-------------------------------
package mypack;
import 
public calss Customer implements Serlizliab;e{
    
private int id;
    
private String name;
    
private Set orders = new HsahSet();

    
//构造方法及set方法get方法
}
一对多关联(one方)
<set 
      name 
= "orders"  --持久化对象的属性
      cascade 
= "save-update" --级联操作
      
<key cloumn = "customer_Id"/> --外键
      
<one-to-many class = "mypack.Order"/> --持久化类
</set>
a.  <set>元素的inverse属性
  在映射一对多的双向关联时,应该在“one”方把inverse属性设为true,这样可提高应用性能。
                    inverse:控制反转,为true表示反转,由它方负责;反之,不反转,自己负责;
                    如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据,
        在建立两个象的双向关系时,应该同时修改关联两端的对象属性:
                    customer.getOrders().add(order);
                    order.setCustomer(customer);

        这样做可提高业务逻辑的独立性,使业务逻辑的程序代码不受Hibernate实现的影响。同理解除双向关系也一样。
b.  级联删除(从数据库删除相关表记录)
         当删除Customer对象时,及联删除Order对象.只需将cascad属性设为delete即可.
          注:删除后的对象,依然存在于内存中,只不过由持久化态变为临时态.
c.  父子关系(逻辑删除,只是解除了关联关系)
         自动删除不再和Customer对象关联的Order对象.只需将cascade属性设为delete-orphan.
                     customer.getOrders().remove(order);
                     order.setCustomer(null);
          注:当关联双方都存在父子关系,就可以把父方的cascade属性设为delete-orphan,所谓父子关系,是由父方来控制子方的生命周期.
                     
       


posted @ 2009-10-16 00:29 独孤行 阅读(3329) | 评论 (2)编辑 收藏