ORMLite使用中出现的问题及解决办法

项目开发中,用到了ORMLite进行数据库操作,其中有三个对象是一对多的关系,在使用过程中出现了一个奇怪的问题。
假设:三个类Company、Person、Car,
Company对应多个Person,Person对应多个Car。

1、出现的问题如下:
①、在Company和Person都声明了外键集合为eager=true,但是从数据库中获取的数据来看,Company拥有的Person集合是EagerForeignCollection的,Person拥有的Car对象
集合时LazyForeignCollection的(注:不知道为什么会是这个情况,但这个是导致出现第二个问题的原因之一)

②、现在有两个Activity: A和B,在A中查询数据库,获取一个Company对象,将这个对象通过Intent传递给B,在B中取出Company对象,并通过这个对象获取Car的信息时,
会出现错误:
Caused by: java.lang.IllegalStateException: Internal DAO object is null. Maybe the collection was deserialized or otherwise constructed wrongly. Use dao.assignEmptyForeignCollection(…) or dao.getEmptyForeignCollection(…) instead

2、问题的分析:
问题①原因不明,问题②分析结果如下:

①:LazyForeignCollection是慢加载模式,在得到这个对象之后,这个对象中并没有具体的对象集合,而是在每一次查数据的时候,直接从数据库中查询;
②:LazyForeignCollection继承BaseForeignCollection,查询数据库是同过BaseForeignCollection#dao对象来进行查询的
③:LazyForeignCollection实现了Serializable接口,可进行序列化,但是成员变量dao 使用transient修饰的,不参与序列化过程;
④:在B中拿到的Car集合时反序列化之后的LazyForeignCollection对象,因为Dao兑现不能序列化,所以为NUll
⑤:在B中查看Car结合时,就会抛出这个异常,可以从LazyForeignCollection的iterator方法来看:

public CloseableIterator<T> iterator() {
        return this.closeableIterator(-1);
    }

  public CloseableIterator<T> closeableIterator(int flags) {
        try {
            return this.iteratorThrow(flags);
        } catch (SQLException var3) {
            throw new IllegalStateException("Could not build lazy iterator for " + this.dao.getDataClass(), var3);
        }
    }

 public CloseableIterator<T> iteratorThrow(int flags) throws SQLException {
        this.lastIterator = this.seperateIteratorThrow(flags);
        return this.lastIterator;
    }


 private CloseableIterator<T> seperateIteratorThrow(int flags) throws SQLException {
         //因为dao对象为NUll,所以就抛出了这个异常
        if(this.dao == null) {
            throw new IllegalStateException("Internal DAO object is null.  Maybe the collection was deserialized or otherwise constructed wrongly.  Use dao.assignEmptyForeignCollection(...) or dao.getEmptyForeignCollection(...) instead");
        } else {
            return this.dao.iterator(this.getPreparedQuery(), flags);
        }
    }

3、解决问题2的方法之一,就是在从数据库中查询到Car数据之后,将数据从LazyForeignCollection中取出,放置到新的Collection对象中,
用Collection替换LazyForeignCollection,相当于在进行数据查询操作之后,进行一次预加载操作:

 //从数据库中获取数据之后,执行一次预加载操作:
     Collection<Company> companies = companyDao.getAllCompanys();
        if(companies!=null){
            Iterator<Company> iteraCom = companies.iterator();
            while(iteraCom.hasNext()){
                Company company = iteraCom.next();
                Collection<Person> person =company.getPersons();
                if(person!=null) {
                    Iterator<Person> iteraPer = person.iterator();
                    while (iteraPer.hasNext()) {
            //对Car集合进行一次预加载操作
                        iteraPer.next().getCars();
                    }
                }
            }
        }
        return companies;
 public Collection<Car> getCars() {
        if(this.cars==null){
            return null;
        }
        if(this.cars instanceof LazyForeignCollection){
            Collection<Car> tmp = new ArrayList<Car>();
            Iterator<Car> iterator = this.cars.iterator();
            while(iterator.hasNext()){
                Car car = iterator.next();
                tmp.add(car);
            }
            this.cars = tmp;
        }
        return cars;
    }

代码修改之后,数据传递正常。
总结:在使用一些第三方开元框架时,如果使用过程中出现了BUG,通过log日志看不出问题时,最好是看下源码,这样容易定位到问题点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值