构建通用的数据库插入操作
在做一些简单的JDBC的API应用时,就老想只用一个方法向数据库不同的表做插入操作,省得用一大堆的insert语句。访问者模式可以实现 [D{=ZOMKA8 l,q
09fd( 对未知的类进行操作,于是就用了这个简化了的模式的实现方案。请高手指正。 在使用访问者模式之前先叙述一点概念性的东西。 8=A/1-r} 静态类型的概念:变量被申明时的类型。实际类型:变量的实际类型。 =W~5F 比如 Object object=new String(); object静态类型是Object,实际类型是String.观察者模式是一个比较难理解的模式,在理解观察者模 QkLb7^@8R -&r!7>oiX 式之前当然应该先理解双重分派的概念。 9Sl@CX) java语言支持静态的多分派跟动态的单分派。java通重载支持静态的多分派。书上的例子: K] T36Nt W>6KDDi <CENTER><ccid_nobr> {t[mwuPaA <table width="400" border="1" cellspacing="0" cellpadding="2" 3^WU4@^U bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> J
V=@\oJ <tr> vk*pj 5 <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> XA'YEGXI( <pre><ccid_code> l[Nz?j3Y DJw7}b\S [hms8(ve- public class Mozi {
8ouynGP h@AN'@s public void ride(Horse h){ rYeRV]| System.out.println("ridding a horse"); b?^Tn/S } 0`H.ZqZHQ public void ride(WhiteHorse w){ ##D1AWr System.out.println("ridding a white horse"); D~L\0a%\ } Kw/'s95?B public void ride(BlackHorse b){ OIvx8@Jh] System.out.println("rdding a black horse"); 5PnJ && } `E[WQw d yY'1G2 public static void main(String[] args){ ,E{1(9 Mozi mozi=new Mozi(); bgf]dpK'K Horse w=new WhiteHorse(); llgccg%lB Horse b=new BlackHorse(); k7DXTd0# mozi.ride(w); *;2~D)m= mozi.ride(b); kKSEg]* } ^}g)py-R } ew l(T $=o1Z}' </ccid_code></pre> Q'a<qV!
6 </td>
pN]kW1. </tr> >J|jA{a </table> u^w)uXzc </ccid_nobr></CENTER> 0eov.Ufy F)fk2K z-L 程序打印输出: sfC1b^v ridding a horse i$.
bm:.F ridding a horse |.\q-H>$ 原因就是对两次ride方法的调用传入的参量不同,但是它们的静态类型是一样的,都是 Horse;这个过程在编译时期就完成了。java通过方 L<VIE4ft =Pr|Nz 法置换支持动态分派。比如 String s1="ab"; Object o=s1+"c"; String s="abc";o.equals(s) 打印true o.equals()方法执行的是String类 vDG`l &YK
f3J? 的equals()方法.java调用对象的真实类型的方法,这就是动态分派。 }xG~{Nk~ }W.Qa37kU 8j8Wo>H 双重分派: ,/7H qR e %Jq`8nzXmF <CENTER><ccid_nobr> kP
@Gf;k <table width="400" border="1" cellspacing="0" cellpadding="2" ;]ea<(X bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> E
acP,[ <tr> F};WI <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> .LNzPdA5 <pre><ccid_code> h+'V {de7 )jti$z7 ]md public abstract class Vistor{ cp}Iy
] u G?k
\7`= protected void processStrig(Object e){ /WQFh if(e instanceof String){ 0 i3*Cj String tmp=(String) e; iiaF:l%Rvq String need="'"+e+"'"; ^O?^W{ System.out.println(nedd); ~W5?I+Bv }else if(e instanceof Integer){ _ 5F%Z?} String need=e.toString(); n(D9amAA System.out.println(need); U^-p5c gW }else if(e instanceof Date){ 0I!DW7/<z Date tmp=(Date) e; D"nXo>AM= String need="'"+tmp.toString()+"'"; }&K2jd v5 } \,$+u~ .... @a(<Sxv_O } dm`"r!6* i2I[J$J& } i(fzX:J
P @WU4% public class ConcreteVisitor extends Visitor{ MO1:H?D 97>DR:Ow[ protected void processString(Object e){ /8;L6N super.processString(e); L]p+{ } u0C
RCvB } CO8OV ID2B_^bc z'<nO </ccid_code></pre> e'nf<D </td> e{ Pp8l%S </tr> ]A8g\^ </table> QOeV
r </ccid_nobr></CENTER> /8sn
kq{ U
uc> 方法的调用Visitor v=new ConcreteVisitor(); v.processString(new String("tt")); #pvv9S<y v.processString()方法在调用的时候会检察v的真实类型,调用真实类型的方法,这个时候就发生了一动态的单分派过程.当子类调用超类的方 bN>YXk_NJ A* 5c^mNGG 法的时候明显的根据instanceof判断的真实类型去执行不同的方法,又发生了一次动态分派的过程.这个就是双重分派的实现。这种方法实现的 M,s-~ecj7 +
_vaCw# 程序比较冗长和容易出错。 UR*/%W=M W .J31 “返传球”方案: Y7J3 h >ZJrEf#b <CENTER><ccid_nobr> :/T%F(MV <table width="400" border="1" cellspacing="0" cellpadding="2" aC_z#
oQI bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> xT3)U: <tr> V08vj$C&k <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> 8s*-\ <pre><ccid_code> 5:AX&2]% )TyUG
KfO public abstract class Vistor{ |*A!y"VC*J ih#V%$w:Z public abstract String processStrig(Object e); &nqG+MUa uI^ YwL[ } yPA|)}V >-zftj/ public class ConcreteVisitor extends Visitor{ |ww,Ai\K .3WQt
Z8 public String processString(WrapperString e){ "cMGfqTZ String tmp= t.toString(); t-;6hF]YV System.out.println(tmp); #c#wo+9/' } LZ075j! 1@lOb= public String processInteger(WrapperInteger e){ %>"/*@Vo3' String tmp=e.toString(); %98zB System.out.println(tmp); <;J!ivp$ ]jIee*G } qJb0ecjF kK_rqgy } hU7:NCM vA V
54 public class abstract Wrapper{ ?w3"L}K1& public abstract String processString(Vistor v); [25N"O } ^Q/E.H!f@ Dqu:6{_ public class WrapperString extends Wrapper{ L ,QsyvA a{Qbg`:H public String processString(Vistor v){ #4Y k*Lh v.processString(this); P 3agt1 } C:n6I`2 public String toString(){ BTthsLEdb ... bG>$<S } @MORy
\*f } Y6nm}sX ? aT}u
`OSV public class WrapperInteger extends Wrapper{ 7
HsV&a7, public String processInteger(Visitor v){ p5qBwTixO v.processString(this); ,Yp]l } IAkAtd public String toString(){ 2pH(
|4 ... ETPq>(a) } pQH ^eIx } f(:)VcI $H*V5SSPg </ccid_code></pre> EupD@A </td> M*] %'C> </tr> y,o.$NP, </table> W|/-c
C6O </ccid_nobr></CENTER> w\;
{
f FPG!<\& 方法的调用: c`HJ:ggziN o74 aIg)
<CENTER><ccid_nobr> U[bgf3;D <table width="400" border="1" cellspacing="0" cellpadding="2" "76+Mr#9 bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> m]Q
z/b <tr> }kXpmgy <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> _e[<Mdi'o <pre><ccid_code> jN9;n63A L#Kb+1Zg Visitor v = new ConcreteVisitor(); at"@x' Wrapper wrapper= new WrapperString(); rJ-UnNGf ] wrapper.processString(v); xfSkM </ccid_code></pre> PjU3.~b# </td> B"V@4 </tr> B<bM4\yPl </table> #
ZAyJ: </ccid_nobr></CENTER> qZN]MH0 _b0s..N+LD 当wrapper.processString()方法执行的时候会检察wrapper的真实类型,这个就产生了一次动态单分派,processString()里面的语句v.pr )YbDkd m=F8$& ocessString()在执行的时候也会检察v的真实类型,动态双重分派就发生了。访问者模式的核心就是“返传球“方案的双重分派。其示意性 \~*\fC8y ",FtJ+! 类图:(注:虚线箭头划错了) /p;s!(l&A D^}dG Bx:[=][ 在一个方法内实现向不同的表插入不同数据的具体实现方案(简化了的):因为整个方案里只需要一个访问者对象,因此使用简化了的访问 NF.!:0 }$7\"'Fq 者模式。因为java基本类型及对应的类是不变模式的实现:因此包装一下这些基本类型和类并实现访问者模式需要的方法。 4^:wt]H 2U!1UY h <CENTER><ccid_nobr> A 0'Xw{~ <table width="400" border="1" cellspacing="0" cellpadding="2" yH9E[.( M9 bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> Y
>TdY <tr> 7w=$;D]n*} <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> :W%~79k <pre><ccid_code>
$-Yt|W public abstract class Wrapper { /<BM%Q public Wrapper() { 8b'r>YKH } 2l88l`)5 public abstract String action(Visitor visitor); tGC@^=)s) :ob':G'[ } SP~J\4B 3fK"i 包装Date类: ,#C["Z/G^ import java.util.Date; ^7
pdW^$ public class WrapperDate extends Wrapper { ?#~f15>k private Date date; +i:y* g^~ public WrapperDate(Date date) { 7 [u
y V this.date=date; 32Z
}[_? } L=;'1,] public String action(Visitor visitor){ Aj*/ToiZQ return( visitor.visit(this)); EI=Ux|j<H } 6|Hz`D6b 3^(VVAN public String toString(){ =/
T}f7\~ if (date==null){ /d)eJBR return "null"; 4Q*H?%j } ~".i by return "'"+date.toString()+"'"; pgW"m= } 0?E#'FLvj Ox;ESxcXr } !uao}JY A;#R(!w.+ </ccid_code></pre> ]P0s:-(G </td> Z{]DFy </tr> e\pbr3Y}| </table> 2_n< </ccid_nobr></CENTER> WS}0S<+B bIeuZ>e0\ 包装Integer类: FQ'{X
~} Q|V(.d^Ac <CENTER><ccid_nobr> XK
_7GK(}" <table width="400" border="1" cellspacing="0" cellpadding="2" nS%MVX bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> /41y`S <tr> [0p^AN`G'' <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> oGWV%;=} <pre><ccid_code> )u{bbjEJ public class WrapperInteger extends Wrapper { 56a-7
OG private Integer value; T6qTS`. K=+Axa!. public WrapperInteger(Integer value) { s2.@zr5A this.value=value; LYka.JV {=RA}}J } V.m.c@ public WrapperInteger(int value){ <%)I@: 1} @I+q this.value=new Integer(value); Z}9<~)_i3 } & LL)- public WrapperInteger(String value){ 3KO9Cn
Ve!D this.value=new Integer(value); |F%J"2' } c;'S8 N@p95 public String action(Visitor visitor){ j'
vkr_Gd_ return( visitor.visit(this)); KHupXF-0 } 9$GS_j public String toString(){ U,2em
if(value==null){ nYFSWF, return "null"; Dsx^4,Ej } -iLrd Q return value.toString(); /! _88Wz& } !$<`J]j#U# } /$!&gi^h o3(`|
Ljf </ccid_code></pre> sF\&;rr% </td> orhaZ8;,( </tr> `LpnKe+
} </table> %+[NdTg^, </ccid_nobr></CENTER> *2fMpg q\#Ha+<!\ 2y306rB+3I 包装String类: eXlUG
6o^fcM <CENTER><ccid_nobr> fhD7h?? <table width="400" border="1" cellspacing="0" cellpadding="2" '
,(:c bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> [7.mh0( <tr> C@*[N <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> #"ZWNCp <pre><ccid_code> d"/&tMA= public class WrapperString extends Wrapper { i._x[N private String wrapper; 2t%_%J public WrapperString( String wrapper) { 3k^2b%q 46uG[%j this.wrapper = wrapper; *4md*JIge } ]Wd{(b ww+y<(em{ public WrapperString( char[] wrap) { LFT{D
L4; wrapper = new String(wrap); zcg2rc% } x<Ez0Zd 9&_VO {t public String action(Visitor visitor) { MP&C
-R return (visitor.vistit(this)); 8mJI F_! } f*HUmSk`Yk PN
:*
o public String toString() { NEVe}|MF-. if(wrapper==null){ C5HSy,r!G return "null";
w6U=Pr } ~
|x&`Zt return "'" + wrapper + "'"; 6k4w7PD7'# } %]y!C#VX X|,2X %m } HT??##F! F1-)A[z </ccid_code></pre> *|AKHg|L </td> R{BxS` </tr> UD:ROfk< </table> CEE%orT7 </ccid_nobr></CENTER> Zi.U{6E T {0R_>v' X=uuAvuW 具体访问者的实现: ^WQn98I .sM>Y( <CENTER><ccid_nobr> k#f(GfNI. <table width="400" border="1" cellspacing="0" cellpadding="2" ~0#]R230# bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> *u@ <tr> [T+q{Jng+ <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> A[ *lqx} <pre><ccid_code> fn4O"67~-/ public class Visitor { ?i\z(> public Visitor() { `$?|
wq6M } `b 1kH=g^ C5pMVxIMq Gc"eB&E[O public String vistit(WrapperString wrap){
1N/R*G return wrap.toString(); (ER
+_I } ch<b[y
public String visit(WrapperInteger value){ C16gy`f return value.toString(); NNFl;^X } /GaY^r<F. public String visit(WrapperDate date){ i3f7Q%0px return date.toString();
-7Q>eL } Bn9;
a } Be_e-dc\3r %|YcG$$}E </ccid_code></pre> yIZc#,o} </td> 2 a1Ov@ </tr> z!%uBoZk> </table> g>ws0'W#| </ccid_nobr></CENTER> X-6duzp% @Msz U WXq{B_ 具体应用类的实现: (e Ui >x^ x >gO5s <CENTER><ccid_nobr> ~4^o+qkX <table width="400" border="1" cellspacing="0" cellpadding="2" M\A&9Qc bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"> A]Bz|16G^, <tr> `{LrN "<h <td bgcolor="e6e6e6" class="code" style="font-size:9pt"> ?5en j)v <pre><ccid_code> |(/#J" Gp%5P}` import java.util.*; #u3i.]lr=" &X3U Y*p public class Test { #?~r)m|U l& 9xe+ Y
e private Visitor visitor = new Visitor(); O!iv^ip (]tbEO( public Test() { }75&HMLgb } cH~nX^)r) Oxk
NhD{q public Visitor getVisitor() { /2%hIYG>aX return visitor; 4ynL}bA } }0>>3`F) y.{%7\>3w Slw!"P'p Db X5+m Q[!.J"V public int insertData(String tablename, List columNameCollection, sqUc!5 List values) { ZPW#)`>8< 7#tW(bKo1h StringBuffer query = new StringBuffer("insert into " + tablename + " ("); :u;8,o>- u'R>S^BU> int count = 0; O/IK kak3$ESH for (Iterator it = columNameCollection.iterator(); it.hasNext(); ) { gxWTc1)f String columName = (String) it.next(); (Aw<*E^ query.append(columName); ;23NQjbS/ query.append(","); W6 c#l } jgjcMrNm query.deleteCharAt(query.length() - 1); z@Mt~RO/ query.append(") values("); !D8\%p]=n for (Iterator it = values.iterator(); it.hasNext(); ) { &/~C~PK Wrapper wrapper = (Wrapper) it.next(); @B;}H+6j7 String tmp = wrapper.action(getVisitor()); Ekb query.append(tmp); %<zx(,xXZ query.append(","); b4 8DS
\ } E,oU(
Z_ query.deleteCharAt(query.length() - 1); V&Bo{
O0 query.append(")"); uj %4a<f #G KA System.out.println(query.toString()); 1@-C~x"pI return count;
Y#z{lA } b`7gPJ6 cZ1FF 4Y g'"pDD
,+| public static void main(String[] args) { rLTwz? Test test = new Test();
1>llui- String tableName = "cutomer"; KrW%3nZl9F List columNameCollection = new ArrayList(); nt)W%' String columName = "name"; A@1ak]
X> String columAge = "age"; xE\H$!/ String columFunctionTime="fuctiontime"; n {cF@z#? columNameCollection.add(columName); Z6(,'oil" columNameCollection.add(columAge); J4pA=8r33J columNameCollection.add(columFunctionTime); >%|v(<>q List values = new ArrayList(); U`FbFWYC String name=null; oYl>xJuL Wrapper wrapper1 = new WrapperString(name); X'9'`;JF Wrapper wrapper2 = new WrapperInteger(1); 0_F<;j_ Wrapper wrapper3= new WrapperDate(new java.util.Date()); >6=r=;!Sm values.add(wrapper1); u.sZJGf| values.add(wrapper2); F/
X f;<o values.add(wrapper3); pX3 YHuIh test.insertData(tableName,columNameCollection,values); B8@X/lU } O~?liYx } NS&3=Kw< m'H%t>HH
</ccid_code></pre> mk,YA- </td> /9!vZIrT </tr> Q1hp3J^ </table> N9roo?,U </ccid_nobr></CENTER> "y#v1@[X
/)`B nld 程序打印结果: lV
YE()h " G)T 3Y^ insert into cutomer (name,age,fuctiontime) values(null,1,'Sat Aug 12 13:46:58 CST 2006') x[UED^B ~J2O
5U"C 这个输出是满足MSSQL执行插入的语法要求的.虽然这样就实现了想要的结果, ixs6SCj[% 但是insertData(String tablename, List columNameCollection, List values) 方法在每次调 Z?nr},vng 用的时候需要输入表名跟该表的列的集合,还是很麻烦,不尽人意,而且不同的数 Ie;9>n 据库的表名是不一样的,因此最好用配置文件来解决这一个问题.
|