随笔-8  评论-39  文章-0  trackbacks-0

写这个 OR Mapping 层的初衷是因为一个朋友租了个虚拟主机,并试图开发一个小系统来扩展自己公司的业务,但因为虚拟主机的限制,不能使用他熟悉的 Hibernate ,他有不想写繁琐的 JDBC ,于是要我帮忙写一个简单的 OR Mapping 层。根据他的具体要求,我将这个小引擎的目标定为:

1.  在 JDBC API 上建立简单的包装。

2.  优化代码,使资源占用( CPU, RAM )尽量少

3.  不支持事务处理

4.  不支持分布式应用

5.  只支持 MySQL 和 ProgressSQL 两种数据库

6.  不需要配置文件

7.  尽量少的第三方包依赖

8.  实体间关系只处理一对一和一对多两种情况,并且只提供延迟加载方式

9.  内置 Connection Pool

 

经过三天的努力,基本的功能已经实现,再经过测试后,准备三月中旬交给朋友用。整个引擎只需要一个 jar 文件, 100k 左右(不需要其它第三方包,当然,数据库的 JDBC 驱动还是需要的 ^O^ ),使用起来也比较简单。对于简单的实体来说,只需要通过注释指定相对应的表和字段就可以了。下面用一个简单的 Book 对象来说明:

 

首先需要定义一个简单实体对象,并加入注释(支持 Java 5 以上环境)

 

@DBTable (name= "Books" )

public class Book {

 

    @DBColumn (name= "id" ,type= "String" ,isKey= true )

    private String id ;

   

    @DBColumn (name= "name" ,type= "String" )

    private String name ;

   

    @DBColumn (name= "isdn" ,type= "String" )

    private String isdn ;

   

    @DBColumn (name= "price" , type= "float" )

    private float price ;

 

    public String getId() {

       return id ;

    }

 

    public void setId(String id) {

       this . id = id;

    }

    ...... (其它的 get, set 方法省略)

 

 

然后再调用引擎的相关新增,修改,删除方法就来完成数据维护工作,

1.  新增

 

       DALEngine engine = new DALEngine();

       Book b = new Book();

       b.setId( "123456789" );

       b.setName( "Think in Java 3 Edition" );

       b.setIsdn( "123-4567-89" );

       b.setPrice(60.5f);

       try {

           engine.create(b);

       } catch (DALException e) {

           log.error(e);

       }

    }

 

2.  基于主键的修改

 

       try {

           engine.update(b);

       } catch (DALException e) {

           log.error(e);

       }

 

3.  基于条件的修改(忽略主键,按条件进行批量更改)

 

       HashMap params = new HashMap();

       params.put( "price" , 20f);

       try {

           engine.update(b, params, "WHERE price > ?" );

        } catch (DALException e) {

           log.error(e);

       }

 

4.  基于主键的删除

 

       try {

           engine.delete(b);

       } catch (DALException e) {

           log.error(e);

       }

 

5.  基于条件的删除(忽略主键,按条件进行批量删除)

 

       HashMap params = new HashMap();

       params.put( "price" , 20f);

       try {

           engine.delete(b.getClass(), params, "WHERE price > ?" );

       } catch (DALException e) {

           log.error(e);

       }

 

 

6.  基于主键的查询

 

       Book b = null ;

       HashMap pks = new HashMap();

       pks.put( "id" , "123456789" );

       try {

           b = engine.get(Book. class , pks);

       } catch (DALException e) {

           log.error(e);

       }

 

7.  基于指定条件的查询

 

       Collection<Book> books = null ;

       HashMap params = new HashMap();

       params.put( "price" , 20f);

       try {

           books = engine.get(Book. class , params, "WHERE price > ?" );

       } catch (DALException e) {

           log.error(e);

       }

 

处理一对一或一对多的实体关系,需要用到 One2One 或 One2Many 注释,比如处理 Order 和 OrderDetail ,需要这样定义实体

 

@DBTable (name= "Orders" )

public class Order {

 

    @DBColumn (name= "id" ,type= "String" ,isKey= true )

    private String id ;

   

    @ One2Many(type= "test.OrderDetail" column= "orderId" cause= "id" )

    private Collection details ;

   

    ......( 其它属性 )

 

    pub lic Collection getDetails() {

       r eturn details ;

    }

 

    public void setDetails(Collection details) {

       this . details = details;

    }

 

    public String getId() {

       return id ;

    }

 

    public void setId( String id) {

       this . id = id;

    }

   

    ...... (其它的 get, set 方法省略)   

}

 

@DBTable (name= "OrderDetails" )

public class OrderDetail {

 

    @DBColumn (name= "id" ,type= "String" ,isKey= true )

    private String id ;

   

    @ Many2One(name= "orderId" ,type= "test.Order" )

    private Order order ;

 

    ......( 其它属性 )

 

    public String getId() {

        return id ;

    }

 

    public void setId(String id) {

       this . id = id;

    }

 

    public Order getOrder() {

       return order ;

    }

 

    public void setOrder(Order order) {

       this . order = order;

    }

   

    ...... (其它的 get, set 方法省略)   

   

}

 

除了以上的根据实体对象来进行操作的方法外,也提供不依赖于实体的简单的 JDBC 包装方法,这时需要用 DataSet 对象来接受查询结果,用 HashMap 来传递参数。例如执行一个查询:

 

    DataSet dataSet = null ;

    HashMap params = new HashMap();

    params.put( "O.Operator" , "Tom" );

    try {

       dataSet = engine.select( "SELECT O.ID, O.Operator, O.DeliveryDate, " +

              "D.ProductId FROM Orders O, OrderDetails D " +

              "WHERE O.id = D.orderId and O.Operator = ?" , params);

    } catch (DALException e) {

       log.error(e);

    }

 

同样,可以用 DALEngine 的 insert, update, delete 方法直接执行 SQL 语句。

 

接下来,我主要是要完成进一步的功能测试和性能测试。但上班后时间可能不是太充裕,我希望能在三月中旬完成,我会在这里继续记录我的测试情况。

posted on 2007-02-25 08:20 Jini 阅读(1609) 评论(13)  编辑  收藏 所属分类: 数据库相关

评论:
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-25 09:45 | alysa
收藏先~  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-25 13:34 | BeanSoft
呵呵, 哥们也很勤奋啊!  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-25 14:30 | 不好说
写得是真的太丑陋了!而且是极其恶心!  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层[未登录] 2007-02-25 14:45 | jini
@不好说

呵呵,能说得具体一点吗?怎么丑陋,哪里恶心啦?  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-25 16:32 | zhyiwww
思路值得借鉴  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-25 16:33 | zhyiwww
@jini
:)  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层[未登录] 2007-02-25 16:51 | jini
@zhyiwww

谢谢!相互学习,共同进步!  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-25 17:24 | bean
我前些天也写了个差不多的
最近懒了,没继续写。  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层[未登录] 2007-02-25 17:39 | jini
@bean

我也是被朋友威逼利诱才放弃假期写的,估计过几天交完差也就不管了,呵呵...  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-27 15:32 | 肖林
思路不错!  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-02-27 21:52 | Jini
@肖林

谢谢鼓励 :)  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-03-13 11:46 | xfans
能公布代码么  回复  更多评论
  
# re: 春节的收获,写了个很简单的OR Mapping层 2007-03-13 11:49 | xfans
想学习下相关的知识,能把代码发给我,让我学习下么?
xfans12000◎163。com 谢了  回复  更多评论