Android ORM数据库框架之-greenDao(二)

这一篇将带给大家greenDao的一些比较高级的用法。
以下内容参考官网

关系型数据库,当然少不了多表关联,SQLite也不例外。那么我们就下来看下greenDao如何建立表关联

  • 一对一 1:1 entity.addToOne(entity,property)
    我们以人和身份证为例,
 /**
         * 人实体
         */
        Entity people = schema.addEntity("People");
        people.addStringProperty("name").primaryKey(); //名字
        people.addIntProperty("age"); //年龄
        /**
         * 身份证
         */
        Entity idcard = schema.addEntity("IdCard");
        idcard.addStringProperty("idcardnum").primaryKey(); //身份证号

        /**
         *  人和身份证 是一对一的关系
         */

        /** 一个人对应一个idcard **/
        Property propertyidcardnum = people.addStringProperty("idcardnum").getProperty();
        people.addToOne(idcard, propertyidcardnum);
        /**  一个idcrad 对应一个name ***/
        Property propertyname = idcard.addStringProperty("name").getProperty();
        idcard.addToOne(people, propertyname);

注意:当我们要建立多表关联的时候,就不在添加id主键了,以为我们这里的主键要当成其他表的外键使用。
上面我们通过entity.addToOne(otherEntity,peoperty)来建立一对一关联,关系为,entity和otherentity通过peroperty来建立关联,其中peoperty在otherentity中式主键,在entity中是外键。这么干说,谁也记不住。看代码

Property propertyidcardnum = people.addStringProperty("idcardnum").getProperty();
        people.addToOne(idcard, propertyidcardnum);

我们将身份证实体中的主键idcardnum,当成外键以一对一的关系添加到people实体中了,就是这么简单。

  • 一对多 1:n addToMany(entity,property)
Entity order = schema.addEntity("Order");
        order.addIntProperty("orderid").primaryKey();
        order.addDoubleProperty("money").notNull();

        /**
         * 建立人与订单的一对多关系
         */
//        Property propertypeoplenum=people.addStringProperty("idcardnum").getProperty();
        Property property = order.addStringProperty("name").getProperty();
        order.addToOne(people, property);
        people.addToMany(order,propertyname).setName("orders");

我在这里建立了一个购物的实体。形成一对多关系 。并将订单中的主键id,以多对一的形式给people当外键。

  • 多对多 m:n
Entity course = schema.addEntity("Course");
        course.addStringProperty("courseid").primaryKey();
        course.addStringProperty("coursename").notNull();


        Property propertyPeopleId = course.addStringProperty("name").getProperty();
        course.addToMany(people,propertyPeopleId);

        Property propertyCourseID = people.addStringProperty("courseid").getProperty();
        people.addToMany(course,propertyCourseID);

,这个就和上面的一样了,我就不再多少了。

需要注意的是,这里的关系特别绕,一不小心就会弄错。
现在,我们去看看生成的实体类有什么区别。

先看People,我们还记得,和身份证是一对一,和订单是一对多,和课程是多对多。

private String name;
    private Integer age;
    private String idcardnum;
    private String courseid;

    /** Used to resolve relations */
    private transient DaoSession daoSession;

    /** Used for active entity operations. */
    private transient PeopleDao myDao;

    private IdCard idCard;
    private String idCard__resolvedKey;

    private List<Order> orders;
    private List<Course> courseList;

看到没,成员变量这里有了IdCard(单一),List< Order> ,List< Course >,确实是形成了上面我们写的关系。

接下来我们看下构造函数

public People(String name, Integer age, String idcardnum, String courseid) {
        this.name = name;
        this.age = age;
        this.idcardnum = idcardnum;
        this.courseid = courseid;
    }

构造函数里面只是几个相关表的主键。。没什么奇怪的。那么我们看下,这个类下面都有什么方法。

有发现,我们会发现这里面有getCourseList 和 getOrderList,我们挑一个来看看

public List<Order> getOrders() {
        if (orders == null) {
            if (daoSession == null) {
                throw new DaoException("Entity is detached from DAO context");
            }
            OrderDao targetDao = daoSession.getOrderDao();
            List<Order> ordersNew = targetDao._queryPeople_Orders(name);
            synchronized (this) {
                if(orders == null) {
                    orders = ordersNew;
                }
            }
        }
        return orders;
    }

看到,这里通过name来查询,为什么呢?因为我们这个name是Order表的外键。哈哈,这样就爽了,都直接给提供方法了,都不同我们自己搞。恩,确实爽。
我们再看看_queryPeople_Orders()方法

public List<Order> _queryPeople_Orders(String name) {
        synchronized (this) {
            if (people_OrdersQuery == null) {
                QueryBuilder<Order> queryBuilder = queryBuilder();
                queryBuilder.where(Properties.Name.eq(null));
                people_OrdersQuery = queryBuilder.build();
            }
        }
        Query<Order> query = people_OrdersQuery.forCurrentThread();
        query.setParameter(0, name);
        return query.list();
    }

不粗,果然是给我们封装好了的。啥,这种查询方法,看不懂?没事,我们后面会介绍到。
多表关联我们看完了,这里你要注意一个坑,那就是 关联的2张表的主键类型一定要一样,别问我为什么。

  • 其他用法
    添加约束 无非就是添加 主键 非空 自增等等。

    如:
order.addIntProperty("orderid").primaryKey();

多线程下

Query<Order> query = people_OrdersQuery.forCurrentThread();

多条件查询

名字叫“乔”和(出生年份大于1970或(出生年份是1970年,出生月等于或大于10(10月)。
     *   QueryBuilder qb = userDao.queryBuilder();
         qb.where(Properties.FirstName.eq("Joe"),
         qb.or(Properties.YearOfBirth.gt(1970),
         qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));
         List youngJoes = qb.list();

或者

Query query = userDao.queryBuilder().where(
         Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))
         .build();
         List joesOf1970 = query.list();

或者

 query.setParameter(0, "Maria");
         query.setParameter(1, 1977);
         List mariasOf1977 = query.list();

嵌套查询

Query query = userDao.queryBuilder().where(
                        new StringCondition("_ID IN " +
                        "(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)").build();

链接查询

   使用连接查询  查询用户名为admin
     Query query = userDao.queryRawCreate(
             ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin");

我们再来看看query的几个list…方法

list() 所有的实体都被加载到内存中,结果是一个ArrayList,比较容易使用
listLazy() 实体按照需求加载,并不会查询完立即加载进内存,只会在需要的时候加载,并且会缓存在一个list之中,并需调用close关闭
listLazyUnCached() 一个虚拟的实体集,任何访问都必须从数据库中加载,必须被关闭
listIterator() 让你便利加载,数据没有被缓存,必须关闭

代码混淆

-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {
    public static java.lang.String TABLENAME;
}
-keep class **$Properties

或者去github上看他们demo如何混淆的。


  • 数据库升级
    本以为这么好个东西数据库升级的一些问题肯定也弄好了,哎,结果。多说无益,我们来看看他封装的代码把。
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this,"persons-db",null);
public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
        PersonDao.dropTable(db, ifExists);
        PeopleDao.dropTable(db, ifExists);
        IdCardDao.dropTable(db, ifExists);
        OrderDao.dropTable(db, ifExists);
        CourseDao.dropTable(db, ifExists);
    }
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"PERSON\"";
        db.execSQL(sql);
    }

看见没,根本没有所谓的数据库升级,还把原来的数据库给删除了。擦。那怎么办呢。别着急,虽然咱垃圾,但是思路还是有的,
怎么办呢?
第一步,我们在生成生成实体类的文件中。

schema.enableKeepSectionsByDefault();//通过次Schema对象添加的所有实体都不会覆盖自定义的代码 或者根据需要添加其他()

这样我们再生成的时候就不会覆盖了。

第二步,咱给出一个连接,你们看吧。(本屌太渣)
greenDao数据库升级

到此为止:
参考资料:greenDao官网

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值