随笔 - 115  文章 - 481  trackbacks - 0
<2006年11月>
日一二三四五六
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(19)

随笔档案(115)

文章档案(4)

新闻档案(1)

成员连接

搜索

  •  

最新评论

阅读排行榜

评论排行榜

在最近的一个项目中,使用了 hibernate+struts ,由于中间没有使用 spring 来管理 bean ,所以我使用了 DAO+Service 来做持久层和业务层。受 spring 对 hibernate 的 template 的封装的影响,我自己实现了一个简单的 hibernateTemplate —— MHibernateTemplate 和调用接口 MHibernateCallback 。在其中包装了错误拦截等动作。所以我的 DAO 就不能直接从 Myecipse 生成了。但由于 Domain bean 太多,而且 DAO 中又是简单的代码重复,所以想到了使用代码生成。刚开始想直接在 Myeclipse 中生成 DAO 的时候使用自己的模版就可以了,但是在网上找了半天都没有相关的信息。后来模仿 easyjtools 使用 velocity 自己做代码生成,但感觉时间不够,所以,就选择了 XDoclet 。

       网上相关的内容不是很多,所以就只有啃 En 版的 XDoclet in Action 。由于我的需求很简单,所以只使用了简单的 template (就是 .xdt )来生成代码,搞了两天,效果还不错。

       比如一个 model :(这个项目的需求比较奇怪,由于要同步,所以每个对象都必须有一个 pkid (包括中间表), 2 就是每个对象有个 dr 标志,表示删除(而不是真正的删除))。

       package com.my.xdoclet;

/**

  * PubCompproper generated by MyEclipse - Hibernate Tools

  * @hasRef

  * 公司性质

  */

 

public class PubCompproper extends BaseDomain implements java.io.Serializable {

 

    // Fields

    /**

      * @pkid

      */

    private String cproPkid ;

    // 系统类型信息

    /**

      * @ref .model name="sytp"

      */

    private PubSystype sytp ;

    // 公司性质编码

    private String cproCode ;

    // 公司性质名称

    private String cproName ;

    // 删除表示

    /**

      * @del

      */

    private String cproDr ;

    // Constructors

 

    /** default constructor */

    public PubCompproper() {

       this .setCproDr( "0" );

    }

 

    // Property accessors

 

    public String getCproPkid() {

       return this . cproPkid ;

    }

 

    public void setCproPkid(String cproPkid ) {

       this . cproPkid = cproPkid ;

    }

 

    public String getCproCode() {

       return this . cproCode ;

    }

 

    public void setCproCode(String cproCode ) {

       this . cproCode = cproCode ;

    }

 

    public String getCproName() {

       return this . cproName ;

    }

 

    public void setCproName(String cproName ) {

       this . cproName = cproName ;

    }

 

    /**

      * @return the sytp

      */

    public PubSystype getSytp() {

       return sytp ;

    }

 

    /**

      * @param sytp the sytp to set

      */

    public void setSytp(PubSystype sytp ) {

       this . sytp = sytp ;

    }

 

    /**

      * @return the cproDr

      */

    public String getCproDr() {

       return cproDr ;

    }

 

    /**

      * @param cproDr the cproDr to set

      */

    public void setCproDr(String cproDr ) {

       this . cproDr = cproDr ;

    }

}

 

其中有一些相关的对象,在 DAO 中要使用到。

看看模版文件

package com.hycs.bs.client.itf;

 

import java.util.List;

 

import <XDtPackage:packageName />.<XDtClass:className />;

 

public interface <XDtClass:className />DAO {

    // 添加

    boolean add(<XDtClass:className /> instance);

   

    <XDtClass:ifHasClassTag tagName="hasRef">

    // 添加

    boolean add(<XDtClass:className /> instance,<XDtField:forAllFields><XDtField:ifHasFieldTag tagName="ref.model" paramName="name"> String <XDtField:fieldTagValue tagName="ref.model" paramName="name" />pkid</XDtField:ifHasFieldTag></XDtField:forAllFields>);  

    </XDtClass:ifHasClassTag>

   

    // 删除

    boolean del(String pkid);

   

    // 更新

    boolean update(<XDtClass:className /> instance);

   

    // 列出所有

    List list();

   

    List list(boolean withDr);

   

    // 得到一个对象

    <XDtClass:className /> get(String pkid);

}

这个是 interface 的模版,其中的模版标签都很简单易懂;

<XDtTagDef:tagDef namespace="Primitive" handler="com.my.xdoclet.customTags.UpperName" />

 

package com.hycs.bs.client.call;

 

import com.hycs.bs.sys.MHibernateTemplate;

import com.hycs.util.Constant;

import com.hycs.util.OidHelper;

import com.hycs.bs.sys.HibernateCodeUtil;

import com.hycs.bs.sys.HibernateUtil;

 

public class <XDtClass:className/>DAOImpl implements <XDtClass:className/>DAO{

    private MHibernateTemplate template;

    <XDtField:forAllFields>

       <XDtField:ifHasFieldTag tagName="ref.model" paramName="name">

           private final <XDtField:fieldType/>DAO <XDtField:fieldTagValue tagName="ref.model" paramName="name"/>dao = new <XDtField:fieldType/>DAOImpl();

       </XDtField:ifHasFieldTag>

    </XDtField:forAllFields>

   

    public <XDtClass:className/>DAOImpl(){

       this.template=new MHibernateTemplate(HibernateUtil.getSessionFactory());

    }

   

    public boolean add(<XDtClass:className/> instance) {

       // TODO Auto-generated method stub

       // add your code and pkid generhere;

       //instance.setCproCode(HibernateCodeUtil.getLastCode("PubCompproper", "cproCode", "cproPkid"));

       //instance.setCproPkid(OidHelper.oidSingle());

      

       return this.template.save(instance);

    }

   

    <XDtClass:ifHasClassTag tagName="hasRef">

    public boolean add(<XDtClass:className/> instance, <XDtField:forAllFields><XDtField:ifHasFieldTag tagName="ref.model" paramName="name"> String <XDtField:fieldTagValue tagName="ref.model" paramName="name" />pkid</XDtField:ifHasFieldTag></XDtField:forAllFields>) {

       // TODO Auto-generated method stub

       <XDtField:forAllFields>

           <XDtField:ifHasFieldTag tagName="ref.model" paramName="name">

              <XDtField:fieldType/> <XDtField:fieldTagValue tagName="ref.model" paramName="name" />=this.<XDtField:fieldTagValue tagName="ref.model" paramName="name"/>dao.get(<XDtField:fieldTagValue tagName="ref.model" paramName="name" />pkid);

              if(<XDtField:fieldTagValue tagName="ref.model" paramName="name" />==null){

                  return false;

              }

              instance.set<XDtPrimitive:upperName value='<XDtField:fieldTagValue tagName="ref.model" paramName="name" />' />(<XDtField:fieldTagValue tagName="ref.model" paramName="name" />);

           </XDtField:ifHasFieldTag>

       </XDtField:forAllFields>

       return this.add(instance);

    }

    </XDtClass:ifHasClassTag>

   

    public boolean del(String pkid) {

       // TODO Auto-generated method stub

       <XDtClass:className /> instance =this.get(pkid);

       if(instance==null||instance.get<XDtField:forAllFields><XDtField:ifHasFieldTag tagName="pkid" ><XDtPrimitive:upperName value="<XDtField:fieldName />" /></XDtField:ifHasFieldTag></XDtField:forAllFields>==null){

           return false;

       }

       instance.set<XDtField:forAllFields><XDtField:ifHasFieldTag tagName="del" ><XDtPrimitive:upperName value="<XDtField:fieldName />" /></XDtField:ifHasFieldTag></XDtField:forAllFields>(Constant.MODEL_DEL);

       return this.template.update(instance);

    }

   

    public <XDtClass:className /> get(String pkid) {

       // TODO Auto-generated method stub

       return (<XDtClass:className />)this.template.get(<XDtClass:className />.class, pkid);

    }

   

    public List list() {

       // TODO Auto-generated method stub

       return this.list(true);

    }

   

    public List list(boolean withDr) {

       // TODO Auto-generated method stub

       if(withDr){

           return HibernateCodeUtil.listWithDr("<XDtClass:className />","<XDtField:forAllFields><XDtField:ifHasFieldTag tagName="del"><XDtField:fieldName /></XDtField:ifHasFieldTag></XDtField:forAllFields>" );

       }else{

           return this.template.getAll(<XDtClass:className />.class);

       }

    }

   

    public boolean update(<XDtClass:className /> instance) {

       // TODO Auto-generated method stub

       <XDtClass:ifHasClassTag tagName="hasRef">

       <XDtClass:className /> temp=this.get(instance.get<XDtField:forAllFields><XDtField:ifHasFieldTag tagName="pkid" ><XDtPrimitive:upperName value="<XDtField:fieldName />" /></XDtField:ifHasFieldTag></XDtField:forAllFields>());

       <XDtField:forAllFields>

           <XDtField:ifHasFieldTag tagName="ref.model" paramName="name">        

              if(instance.get<XDtPrimitive:upperName value='<XDtField:fieldTagValue tagName="ref.model" paramName="name" />' />()==null){                

                  instance.set<XDtPrimitive:upperName value='<XDtField:fieldTagValue tagName="ref.model" paramName="name" />' />(temp.get<XDtPrimitive:upperName value='<XDtField:fieldTagValue tagName="ref.model" paramName="name" />' />());

              }

           </XDtField:ifHasFieldTag>

       </XDtField:forAllFields>

      

       </XDtClass:ifHasClassTag>

       return this.template.update(instance);

    }

}

这是个比较复杂的模版了,是 DAO 的具体实现,

在写这个模版的时候,我遇到了几个问题,

1 就是标签的嵌套,比如 <XDtPrimitive:upperName value='<XDtField:fieldTagValue tagName="ref.model" paramName="name" />' /> ,开始内部标签都使用转义符,结果搞不定,网上找没有任何相关的内容,后来直接在外层使用 ’ (就象 js ),搞定。

2 就是对于标签的内容的首字符大写,没有提供这个功能的标签,使用了自定义的:

package com.my.xdoclet.customTags;

 

import java.util.Properties;

 

import xdoclet.XDocletTagSupport;

 

public class UpperName extends XDocletTagSupport {

    public String upperName(Properties attribute){

       String value=attribute.getProperty("value");

       String upper= upper(value);

       return upper;

    }

   

    private static String upper(String value){

       return value.toUpperCase().substring(0,1)+value.substring(1);

    }

}

并在模版文件中使用 <XDtTagDef:tagDef namespace="Primitive" handler="com.my.xdoclet.customTags.UpperName" /> 来应用就直接能在模版文件中使用 <XDtPrimitive:upperName > 来使用了,

下面是 bulid.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>

 

<project name= "xdocletExample" default= "doall" basedir= "." >

    <property name= "xdoclet.lib.dir" location= "${basedir}/lib" />

    <property name= "gen.src.dir" location= "${basedir}/target" />

    <property name= "src.dir" location= "${basedir}/src" />

    <property name= "template.dir" location= "${basedir}/template" />

    <property name= "customtag.dir" location= "${basedir}/bin" />

 

    <path id= "xdoclet.lib.path" >

       <fileset dir= "${xdoclet.lib.dir}" includes= "*.jar" />

    </path>

 

    <taskdef name= "xdoclet" classname= "xdoclet.DocletTask" classpathref= "xdoclet.lib.path" />    

   

    <target name= "init" />

 

    <target name= "daogener" depends= "init" >

       <xdoclet destdir= "${gen.src.dir}" >

           <fileset dir= "${src.dir}" includes= "**/*.java" />

           <template templateFile= "${template.dir}/daointerface.xdt" acceptInterfaces= "false" acceptAbstractClasses= "false" destinationfile= "{0}DAO.java" />

       </xdoclet>

    </target>

 

    <target name= "daoimplgener" depends= "init" >

       <xdoclet destdir= "${gen.src.dir}" >

           <fileset dir= "${src.dir}" includes= "**/*.java" />

           <template templateFile= "${template.dir}/daoimpl.xdt" acceptInterfaces= "false" acceptAbstractClasses= "false" destinationfile= "{0}DAOImpl.java" />

       </xdoclet>

    </target>

 

    <target name= "doall" depends= "daogener,daoimplgener" />

</project>

 

build 一下:

生成的代码如下:

package com.hycs.bs.client.itf;

 

import java.util.List;

 

import com.my.xdoclet.PubCompproper;

 

public interface PubCompproperDAO {

    // 添加

    boolean add(PubCompproper instance);

    // 添加

    boolean add(PubCompproper instance, String sytppkid);  

    // 删除

    boolean del(String pkid);

    // 更新

    boolean update(PubCompproper instance);

    // 列出所有

    List list();

    List list(boolean withDr);

    // 得到一个对象

    PubCompproper get(String pkid);

}

这个是接口

 

package com.hycs.bs.client.call;

 

import com.hycs.bs.sys.MHibernateTemplate;

import com.hycs.util.Constant;

import com.hycs.util.OidHelper;

import com.hycs.bs.sys.HibernateCodeUtil;

import com.hycs.bs.sys.HibernateUtil;

 

public class PubCompproperDAOImpl implements PubCompproperDAO{

    private MHibernateTemplate template;

           private final com.my.xdoclet.PubSystypeDAO sytpdao = new com.my.xdoclet.PubSystypeDAOImpl();

    public PubCompproperDAOImpl(){

       this.template=new MHibernateTemplate(HibernateUtil.getSessionFactory());

    }

    public boolean add(PubCompproper instance) {

       // TODO Auto-generated method stub

       // add your code and pkid generhere;

       //instance.setCproCode(HibernateCodeUtil.getLastCode("PubCompproper", "cproCode", "cproPkid"));

       //instance.setCproPkid(OidHelper.oidSingle());

       return this.template.save(instance);

    }

    public boolean add(PubCompproper instance,  String sytppkid) {

       // TODO Auto-generated method stub

              com.my.xdoclet.PubSystype sytp=this.sytpdao.get(sytppkid);

              if(sytp==null){

                  return false;

              }

              instance.setSytp(sytp);

       return this.add(instance);

    }

    public boolean del(String pkid) {

       // TODO Auto-generated method stub

       PubCompproper instance =this.get(pkid);

       if(instance==null||instance.getCproPkid==null){

           return false;

       }

       instance.setCproDr(Constant.MODEL_DEL);

       return this.template.update(instance);

    }

    public PubCompproper get(String pkid) {

       // TODO Auto-generated method stub

       return (PubCompproper)this.template.get(PubCompproper.class, pkid);

    }

    public List list() {

       // TODO Auto-generated method stub

       return this.list(true);

    }

    public List list(boolean withDr) {

       // TODO Auto-generated method stub

       if(withDr){

           return HibernateCodeUtil.listWithDr("PubCompproper","cproDr" );

       }else{

           return this.template.getAll(PubCompproper.class);

       }

    }

    public boolean update(PubCompproper instance) {

       // TODO Auto-generated method stub

       PubCompproper temp=this.get(instance.getCproPkid());

              if(instance.getSytp()==null){                

                  instance.setSytp(temp.getSytp());

              }

       return this.template.update(instance);

    }

}

这个是代码。

于是我的工作就很简单了,适用 Myeclipse 直接从 DataExplor 中生成 Domain bean 和映射文件,改一下关联,在 domain 中添加必要的 XDoclet 标记, build ,就可以专著于具体的业务了。

但这个代码还有点问题就是当遇到一个类有多个关联对象的时候,在生成的一些方法上,要自己手动增加或者删除一个 ”,” 。这个还要继续学习。

同时 XDoclet 提供了很好的扩展机制,这个也要继续研究。

再次就是我在想 XDoclet 中有没有直接使用标签来定义标签的功能,或者在模版内定义变量??

easyjweb 使用 XDoclet 来生成代码也会是很简单而且稳定的。

(注:本文作者,EasyJF开源团队 stef_wu,转载请保留作者声明!)

posted on 2006-11-28 09:51 简易java框架 阅读(1941) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: