用户操作
[即时聊天] [发私信] [加为好友]
纯月ID:danny_xcz
858430次访问,排名41好友2人,关注者91
danny_xcz的文章
原创 296 篇
翻译 3 篇
转载 25 篇
评论 639 篇
纯月的公告
最近评论
zhengjiashuai:收藏了先
zjxzou:bucuo~
yu3350360:收藏了先 呵呵
henhaohll:有些意思啊!呵呵 ..
sap99:www.sap99.com/,SAP99资料多多

SAP免费资料下载
http://www.sap99.com

有很多的学习资料,推荐一下,
文章分类
收藏
    相册
    Blog用途
    我的相册
    Java Desktop
    Open Source
    友情链接
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 J2EE中几种面向对象的数据库映射访问策略:收藏

    新一篇: 创业过程犹如越狱 一个创业者的Prison Break | 旧一篇: Struts 2.0 解读笔记

    几种面向对象的数据库访问策略:

    1 JDBC
    是最原始的方法,写sql语句,维护性差


    下面面向对象的方法:

    例如update: 要先取出对象,更新对象,然后再保存

    OrderInfo order = orderService.getOrder(orderId);
    order.setStatus(new Integer(2));
    orderService.updateOrder(order);

    2 Hibernate

    使用Hql

    3 iBatis
    将查询和更新放在maps文件中

      <dynamic-mapped-statement name="searchProductList" result-map="result">
        select productid, name, descn, category from product
        <dynamic prepend="where">
          <iterate property="keywordList" open="(" close=")" conjunction="OR">
            lower(name) like #keywordList[]# OR lower(category) like #keywordList[]# OR lower(descn) like #keywordList[]#
          </iterate>
        </dynamic>

    4 EasyDBO:

    有三种实现方法,我们只看其中采用annotation的
    @Table(tableName="Customer")
    public class Customer implements Serializable {
    来确定表名

    采用反射的方法,不需要配置文件:
     public List getRootCustomers() {  
      return this.dao.query(Customer.class,"(parent_id is null or parent_id='')");
     }

      List list=dao.query(CustomerPrice.class, "customer_id="+cu.getId()+" and product_id="+p.getId()+" order by vdate desc");

    该方法已经和ADODB很像了,但和adodb不同的是,仍然没有实现完全自动的Plain SQL转换到PO.

    5 PHP's ADODB的j2ee移植

    以jdbc查询sql为基础,通过反射,范型等方法自动装载。
    adodb的方法和上面的easydbo很像,不过在obj到sql的生成上更加成熟一些,驱动也更加多

    对于查询

        /////////////////////////////////////////////////////////////////////////////
        //Function: 完成ResultSet对象向ArrayList对象为集合的对象的转化
        //Para:sql,指定的查询Sql
       //Para:className,Sql相对应得JavaBean/FormBean类的名字
       //Return:以类className为一条记录的结果集,完成ResultSet对象向ArrayList对象为集//合的className对象的转化
      //////////////////////////////////////////////////////////////////////////////
      public ArrayList Select(String sql,String className){
        ArrayList paraList=new ArrayList();
        try{
          if (conn == null){
            Connection();
          }
          PreparedStatement stmt = conn.prepareStatement(sql);
          ResultSet rs = stmt.executeQuery();
          String recordValue="";
          Object c1=null;
          paraList=new ArrayList();
          ResultSetMetaData rsmd = rs.getMetaData();
          int columnCount = rsmd.getColumnCount();
          while (rs.next()){
              c1=Class.forName(className).newInstance();
              for (int i=1; i<=columnCount; i++) {
                if(rs.getString(rsmd.getColumnName(i))!=null){
                  recordValue=rs.getString(rsmd.getColumnName(i));
                }else{
                  recordValue="";
                }
                Method m=c1.getClass().getMethod(getSetMethodName(rsmd.getColumnName(i)),new Class[]{recordValue.getClass()});
                m.invoke (c1, new Object[]{recordValue});
              }
              paraList.add(c1);
          }
        }catch(SQLException ex){
         
        }catch(ClassNotFoundException e){
        }catch(NoSuchMethodException e) {
        }catch(InvocationTargetException e){
        }catch (IllegalAccessException e){
        }catch(InstantiationException e){
        } finaly{
            closeConnection();
        return paraList;
        }
          }


       //Function:取得用户列表
      //Para:
      //Return:返回用户列表
      /////////////////////////////////////////////////////////////////////////////
      public ArrayList getUsers(){
          ArrayList ret=null;
          DatabaseManage db=new DatabaseManage();
          String sql=" select usr_id,usr_name "
              +" from users " ;  //该方法的好处是SQL可以随便写,需要的字段也可以随便写,甚至免去了持久层的LazyLoad
          ret=db.Select(sql,"com.domain.User");
          return ret;
      }

    对于单张表,用PO/Formbean来存放
    如果有关联多张表,需要一个VO/Map来存放

    对于保存和更新
        检查对象里面的每一个属性,如果不是null,就组成SQL语句,
        更新的时候,先查出这个对象,如果属性不是null,并且属性值变了,才将该属性组成SQL语句
       
    这种方法和Hibernate/Ibatis相比可能牺牲一些性能,但是免去了大量的配置文件,如果对字段有特殊的要求,可以
    通过annotation来定义。

    Annotation可是个好东西,根据jdk手册:Annotations can be read from source files, class files, or reflectively at run time.
    所以可以充分利用反射读取annotation来减少代码。
    下面是一些例子
    @com.acme.util.Name(first=Alfred, middle=E., last=Neuman)
    @Table(tableName="Customer")
    @ManyToOne(column = "parent_id", fieldType=java.util.HashSet.class,type = Customer.class,lazy=false)
    读取的方法是在反射里面使用下面的方法
    <T extends Annotation> T xxx = getAnnotation(Class<T> annotationClass) 

    当然,实现必须声明annotationClass,下面是手册的一个简单例子
    /**
     * Describes the Request-For-Enhancement(RFE) that led
     * to the presence of the annotated API element.
       定义一个标签记号
     */
    public @interface RequestForEnhancement {
        int    id();
        String synopsis();
        String engineer() default "[unassigned]";
        String date();    default "[unimplemented]";
    }

    这个标签,和它的属性都在上面声明了,下面是某个函数中需要用到这个标签的示例
    @RequestForEnhancement(
        id       = 2868724,
        synopsis = "Enable time-travel",
        engineer = "Mr. Peabody",
        date     = "4/1/3007"
    )
    public static void travelThroughTime(Date destination) { ... }

    因此我们如果想要调用这个标签
    for (Method m : Class.forName('假设是travelThroughTime所在的类名').getMethods()) {
             if (m.isAnnotationPresent(RequestForEnhancement.class)) {
                 RequestForEnhancement rfe = m.getAnnotation(RequestForEnhancement.class);
                 下面就可以取得rfe的属性了
             }
          }

    Commons Attributes也是一个替代jdk标准annotation的方案


    PHP中的ADODB之所以强大,高效是在于PHP数组的强大和弱变量定义的方便。

    当然这里的每一个对象就相当于对应数据库的一张表,这样也很好。
    因为在业务相当复杂的时候,关联要尽量少用,把业务精心设计在数据库表上面而非java对象的集合的关联上。
    在大型应用中,一般1:1的关联都多使用View来处理关联,1:n和n:n的关联,建议还是在DAO里面手动保存,装载和更新


    ===================
    此外还有一些方法,可以方便我们快速的将RS变成可操作的对象,简单举几个例子如下

    1 commons dbutils

    Custom RowProcessor

    java.lang.Object[] toArray(java.sql.ResultSet rs)
              Convert a ResultSet row into an Object[].
     java.lang.Object toBean(java.sql.ResultSet rs, java.lang.Class type)
              Convert a ResultSet row into a JavaBean.
     java.util.List toBeanList(java.sql.ResultSet rs, java.lang.Class type)
              Convert a ResultSet into a List of JavaBeans.
     java.util.Map toMap(java.sql.ResultSet rs)
              Convert a ResultSet row into a Map.


    Custom BeanProcessor


     java.lang.Object toBean(java.sql.ResultSet rs, java.lang.Class type)
              Convert a ResultSet row into a JavaBean.
     java.util.List toBeanList(java.sql.ResultSet rs, java.lang.Class type)
              Convert a ResultSet into a List of JavaBeans.


    2 commons beanutils
    ResultSetDynaClass (Wraps ResultSet in DynaBeans)

      Connection conn = ...;
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery
        ("select account_id, name from customers");
      Iterator rows = (new ResultSetDynaClass(rs)).iterator();
      while (rows.hasNext()) {
        DynaBean row = (DynaBean) rows.next();
        System.out.println("Account number is " +
                           row.get("account_id") +
                           " and name is " + row.get("name"));
      }
      rs.close();
      stmt.close();

    ============

    总得来说,使用反射机制可以极大得方便对数据的各种操作,使操作变得更加透明,无需配置文件 

    发表于 @ 2007年02月07日 14:27:00|评论(loading...)|编辑

    新一篇: 创业过程犹如越狱 一个创业者的Prison Break | 旧一篇: Struts 2.0 解读笔记

    评论

    #yuyebuguijia 发表于2007-02-09 14:15:00  IP:
    学习了.
    #SHauCle 发表于2007-02-09 20:31:21  IP: 58.34.70.*
    如果两年前发的话,应该很有价值
    #txkr 发表于2007-02-11 12:30:20  IP: 60.29.6.*
    您好!我是easyJF团队的竹雨林风。看到您对EasyDBO的看法,很想和您聊一聊。希望您多对EasyJF加以关注并提出批评和改进意见。谢谢!
    #ProvidenceZY 发表于2007-02-11 20:09:58  IP:
    "该方法已经和ADODB很像了,但和adodb不同的是,仍然没有实现完全自动的Plain SQL转换到PO."这句话怎么理解?您所说的完全自动的plain sql转换到po是什么意思?
    #ubuntuer 发表于2007-02-12 10:02:34  IP: 172.23.11.*
    学习了。
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 纯月