隨筆-35  評(píng)論-97  文章-0  trackbacks-0

          EasyDBO上對(duì)象關(guān)聯(lián)還是存在很大問(wèn)題。

          其中一個(gè),添加對(duì)象時(shí),沒(méi)能將被關(guān)聯(lián)對(duì)象的主鍵(由數(shù)據(jù)庫(kù)生成)插入到關(guān)聯(lián)對(duì)象的外鍵上。

          注:

          (1) EasyDBO的一對(duì)一關(guān)聯(lián)中,外鍵在關(guān)聯(lián)對(duì)象方。

          Class A{

          .....

          B b ;

          }

           

          Class B{

          }

          對(duì)應(yīng)于實(shí)體A的數(shù)據(jù)庫(kù)表有外鍵,如 fk_b

           

          (2) EasyDBO的一對(duì)多關(guān)聯(lián)中,外鍵在被關(guān)聯(lián)對(duì)象方(多方)。

          Class A{

          .....

          List<B> bList ;

          }

           

          Class B{

          A a;

          }

          對(duì)應(yīng)于實(shí)體B的數(shù)據(jù)庫(kù)表有外鍵,如 fk_a

           

          在解決這個(gè)問(wèn)題中,對(duì)源碼做一些的修改:

          1、首先解決如果是數(shù)據(jù)庫(kù)生成的主鍵(如auto_increment類型),在DatabaseDAO添加getGeneratedKey()方法。

              public Serializable getGeneratedKey()
              
          {
                  
          if(prepared==null){
                      
          return null;
                  }

                  Serializable ret 
          =null;
                  ResultSet rs 
          = null;
                  
          try
                  
          {
                      rs 
          = prepared.getGeneratedKeys();
                      
          if(rs.next())
                      
          {
                          ret 
          = (Serializable)rs.getObject(1);
                          logger.info(
          "get the GeneratedKey:" + ret);
                      }

                  }

                  
          catch(SQLException e)
                  
          {
                      e.printStackTrace();
                  }

                  
          finally
                  
          {
                      
          if(rs != null)
                          
          try
                          
          {
                              rs.close();
                          }

                          
          catch(SQLException e)
                          
          {
                              e.printStackTrace();
                          }

                  }

                  
          return ret;
              }

          2、在EasyJDBEngine中添加generatedKey字段和getter方法。

              private Serializable generatedKey;
              
              
              
          public Serializable getGeneratedKey()
              
          {
                  
          return generatedKey;
              }

             在EasyJDBEngine的public boolean add(DBObject obj)方法中try的括號(hào)末尾添加

          generatedKey  = dba.getGeneratedKey();

              public boolean add(DBObject obj) // 添加一個(gè)對(duì)象
                  ...
                  
          try {

                              ...... 
                      generatedKey  = dba.getGeneratedKey();
                  }
           catch (Exception e) {

          3、EasyJDB中添加以下方法:

              private Object setObjectGenIdValue(Object obj){
                  BeanWrapper wrapper 
          = new BeanWrapper(obj);
                  DBTable dbTable 
          = findTable(obj.getClass());
                  String idFieldName 
          = dbTable.getPoperty(dbTable.getId());
                  
          if(wrapper.getPropertyValue(idFieldName)==null && StringUtils.isNotEmpty(dbEngine.getGeneratedKey())){
                      Object javaPropertyValue 
          = wrapper.convertIfNecessary(String.valueOf(dbEngine.getGeneratedKey()),
                                                                              dbTable.getType(idFieldName));
                      wrapper.setPropertyValue(idFieldName, javaPropertyValue);
                      System.out.println(
          "setting id.");
                      
          return javaPropertyValue;
                  }

                  
          return null;
              }


              
          private Object getObjectIdValue(Object obj){
                  BeanWrapper wrapper 
          = new BeanWrapper(obj);
                  DBTable dbTable 
          = findTable(obj.getClass());
                  String idFieldName 
          = dbTable.getPoperty(dbTable.getId());
                  
          if(StringUtils.isNotEmpty(wrapper.getPropertyValue(idFieldName))){
                      
          return wrapper.getPropertyValue(idFieldName);
                  }

                  
          return null;
              }


              
          private void setClassFieldValue(Object target,ClassField classField,Object value){
                  BeanWrapper wi
          =new BeanWrapper(target);
                  DBTable dbTable 
          = findTable(target.getClass());
                  wi.setPropertyValue(dbTable.getPoperty(classField.getColumn()),value);
              }

          EasyJDB中的public boolean add(Object obj)方法改為:

              public boolean add(Object obj)
              
          {
                  logger.debug(
          "把對(duì)象obj保存到數(shù)據(jù)庫(kù)中");
                   
          boolean ret = dbEngine.add(obj2dbo(obj));
                   setObjectGenIdValue(obj);
          ///如果是新添加的記錄,且主鍵為數(shù)據(jù)庫(kù)生成,那么將主鍵值返回賦給對(duì)象
                   if(ret)ret = ret & addRelativeObject(obj);
                  
          return ret;
              }

           

           EasyJDB中的private boolean addRelativeObject(Object obj)方法改為:

           

              private boolean addRelativeObject(Object obj)
              
          {
                  
          boolean ret = true;
                  DBTable table 
          = findTable(obj.getClass());
                  
          if(table != null)
                  
          {
                      BeanWrapper wrapper 
          = new BeanWrapper(obj);
                      java.util.Iterator it 
          = table.getClassField().entrySet().iterator();
                      
          while(it.hasNext())
                      
          {
                          
          // 嘗試處理其它字段
                          Map.Entry en = (Map.Entry)it.next();
                          String propertyName 
          = (String)en.getKey();
                          ClassField classField 
          = (ClassField)en.getValue();
                          
          // System.out.println(classField.getClass()+":"+propertyName);
                          if(classField instanceof ManyToManyField && wrapper.isReadableProperty(propertyName))
                          
          {
                              
          // 處理多對(duì)多
                              Object value = wrapper.getPropertyValue(propertyName);
                              
          // System.out.println("值內(nèi)容"+value.getClass());
                              if(value != null && value instanceof Collection)
                              
          {
                                  java.util.Iterator es 
          = ((Collection)value).iterator();
                                  
          while(es.hasNext())
                                  
          {
                                      Object element 
          = es.next();
                                      ret 
          = ret & this.saveOrUpdate(element);
                                      
          // 保存關(guān)聯(lián)的第三方表
                                      ManyToManyField field = (ManyToManyField)classField;
                                      
          /*
                                       * DBTable table2=findTable(element.getClass());
                                       * if(table2!=null) { ManyToManyField field2=null;
                                       * java.util.Iterator
                                       * inf2=table2.getClassField().values().iterator();
                                       * while(inf2.hasNext()) { ClassField
                                       * ff=(ClassField)inf2.next();
                                       * if(ff.getTableName().equals(field.getTableName()) &&
                                       * ff.getType()==obj.getClass()) {
                                       * field2=(ManyToManyField)ff; } }
                                       
          */

                                      String sql 
          = "insert into " + field.getTableName() + "(" + classField.getColumn() + ","
                                                      
          + field.getTagColumn() + ") values(?,?)";
                                      java.util.Collection paras 
          = new java.util.ArrayList();
                                      paras.add(wrapper.getPropertyValue(classField.getKey()));
                                      BeanWrapper wrapper2 
          = new BeanWrapper(element);
                                      paras.add(wrapper2.getPropertyValue(field.getTagKey()));
                                      
          try
                                      
          {
                                          
          this.execute(sql, paras);
                                      }

                                      
          catch(Exception e)
                                      
          {
                                          logger.error(
          "插入多對(duì)多關(guān)系時(shí)出錯(cuò)!");
                                          e.printStackTrace();
                                      }

                                      
          // }
                                  }

                              }

                          }

                          
          else if((classField instanceof ManyToOneField) && wrapper.isReadableProperty(propertyName))
                          
          {
                              
          // 處理一對(duì)多
                              Object value = wrapper.getPropertyValue(propertyName);
                              
          if(value != null && value instanceof Collection)
                              
          {
                                  java.util.Iterator es 
          = ((Collection)value).iterator();
                                  
          while(es.hasNext())
                                  
          {
                                      Object item 
          = es.next();
                                      setClassFieldValue(item,classField,obj);
          //設(shè)置關(guān)聯(lián)值
                                      ret = ret & this.saveOrUpdate(item);
                                  }

                              }

                          }

                          
          else if((classField instanceof OneToOneField) && wrapper.isReadableProperty(propertyName))
                          
          {
                              
          // 處理一對(duì)一
                              Object value = wrapper.getPropertyValue(propertyName);
                              
          if(value != null)
                              
          {
                                  ret 
          = ret & this.saveOrUpdate(value);
                                  
          if(StringUtils.isNotEmpty(getObjectIdValue(value)))
                                  
          {
                                      setClassFieldValue(obj, classField, value);
          //設(shè)置關(guān)聯(lián)值
                                      update(obj);//更新一下數(shù)據(jù),將關(guān)聯(lián)的對(duì)象主鍵作為外鍵
                                  }

                              }

                          }

                      }

                  }

                  
          return ret;
              }

          EasyJDB中的public boolean update(Object obj)方法改為:

              public boolean update(Object obj)
              
          {
                  logger.info(
          "更新持久層中的數(shù)據(jù)表對(duì)象");
                  
          boolean ret = dbEngine.update(obj2dbo(obj));
          //        ret = ret & this.addRelativeObject(obj);//這句很容易會(huì)導(dǎo)致死循環(huán),先不要了
                  return ret;
              }

          EasyJDB中的public boolean saveOrUpdate(Object obj)方法改為:

              public boolean saveOrUpdate(Object obj)
              
          {
                  
          // logger.info("把對(duì)象持久化到數(shù)據(jù)庫(kù)中,先償試添加,若無(wú)法保存則執(zhí)行修改操作");
                  boolean ret = false;
                  
          try
                  
          {
                      Object id 
          = getObjectIdValue(obj);
                      
                      
          if(id == null)
                      
          {
                          ret 
          = add(obj);
                      }


                      
          else
                      
          {
                          
          if(get(obj.getClass(), id) != null)
                              ret 
          = update(obj);
                          
          else
                              ret 
          = add(obj);
                      }

                  }

                  
          catch(Exception e)
                  
          {
                      
          //這里的也先不要的,很容易導(dǎo)致死循環(huán)
                      
          // 出錯(cuò),進(jìn)一步嘗試使用原始的方法進(jìn)行更改
          //            if(add(obj))
          //            {
          //                return true;
          //            }
          //            return update(obj);
                      e.printStackTrace();
                  }

                  
          return ret;
              }

           

          解釋一下:

          這里處理的不包括多對(duì)多的關(guān)系,很少用到,暫時(shí)不管。

          解決的思路是,如果是自增(數(shù)據(jù)庫(kù)生成的id),那么獲取這個(gè)id,并回賦給對(duì)象,對(duì)象有了主鍵值(每個(gè)這樣的對(duì)象都回賦主鍵值),關(guān)聯(lián)就有了導(dǎo)航。

          在一對(duì)一關(guān)系處理中,因?yàn)槭窍炔迦腙P(guān)聯(lián)對(duì)象數(shù)據(jù),然后在插入被關(guān)聯(lián)對(duì)象數(shù)據(jù)。但是關(guān)聯(lián)對(duì)象需要知道被關(guān)聯(lián)的主鍵值,而被關(guān)聯(lián)的主鍵值是在最后插入數(shù)據(jù)后回賦的,所以,采取從新將對(duì)象關(guān)聯(lián),并更新數(shù)據(jù)。

                 setClassFieldValue(obj, classField, value);//設(shè)置關(guān)聯(lián)值
                 update(obj);//更新一下數(shù)據(jù),將關(guān)聯(lián)的對(duì)象主鍵作為外鍵

          在處理一對(duì)多(也即多對(duì)一)關(guān)系中,如一開(kāi)就提到的“EasyDBO的一對(duì)多關(guān)聯(lián)中,外鍵在被關(guān)聯(lián)對(duì)象方(多方)”,數(shù)據(jù)插入順序同一對(duì)一的一樣,先關(guān)聯(lián)對(duì)象,后被關(guān)聯(lián)對(duì)象,所以,在這里只需要在被關(guān)聯(lián)對(duì)象插入前更新關(guān)聯(lián)就可以了

          setClassFieldValue(item,classField,obj);//設(shè)置關(guān)聯(lián)值

          比較明顯,將一對(duì)多的關(guān)系轉(zhuǎn)換成了多個(gè)一對(duì)一了?;蛟S這樣不是很好,但是,在原有的架構(gòu)上,比較難做更大修改。

           

          EasyDBO有一些主鍵生成器的,不知對(duì)對(duì)象關(guān)聯(lián)上主鍵的處理上有沒(méi)有獨(dú)特的解決方法,待探索...

          淺見(jiàn),不當(dāng)?shù)牡胤綒g迎指正~~~~~~~~

          posted on 2007-07-02 18:15 三告習(xí)習(xí) 閱讀(1205) 評(píng)論(3)  編輯  收藏 所屬分類: easyJF-projects

          評(píng)論:
          # re: [EasyDBO] EasyDBO上對(duì)象關(guān)聯(lián)問(wèn)題的一個(gè)簡(jiǎn)單解決方法 2007-07-19 12:13 | hingwu
          我在前面的項(xiàng)目中也使用到了EasyJDB,也發(fā)現(xiàn)了不少bug,有些甚至是莫名其妙的錯(cuò)誤,希望以后有得提升。  回復(fù)  更多評(píng)論
            
          # re: [EasyDBO] EasyDBO上對(duì)象關(guān)聯(lián)問(wèn)題的一個(gè)簡(jiǎn)單解決方法 2007-07-19 17:29 | John Ong
          這種shit framework 不用也罷!  回復(fù)  更多評(píng)論
            
          # re: [EasyDBO] EasyDBO上對(duì)象關(guān)聯(lián)問(wèn)題的一個(gè)簡(jiǎn)單解決方法 2007-07-19 21:44 | 三告習(xí)習(xí)
          @John Ong
          盡管不是很完善,從中還能學(xué)到多少東西的,至少能提醒自己寫的時(shí)候不要這樣冒險(xiǎn),在處理這些地方需要慎重些
            回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 岳阳市| 太谷县| 耿马| 嵩明县| 东安县| 金塔县| 六枝特区| 阿尔山市| 旅游| 东乡县| 绿春县| 长宁区| 个旧市| 台北县| 钟祥市| 赤壁市| 西充县| 城固县| 若尔盖县| 阿合奇县| 米易县| 广宁县| 连城县| 伊金霍洛旗| 贡觉县| 珠海市| 启东市| 沛县| 扎囊县| 英山县| 长春市| 阿勒泰市| 洛南县| 阳谷县| 池州市| 亚东县| 平遥县| 宁乡县| 白朗县| 临西县| 鄄城县|