Skip to content

Android-Jungle/android-simple-ORM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 

Repository files navigation

android-simple-ORM 简介

1、简介

android-simple-ORM 如你所见,是一款 Android 平台上基于 SQLite 的简易 ORM 框架。特点如下:

  • 方便易用;
  • 接口众多;
  • 利用反射自动 Load & Save。

由于是动态 反射 型库,显然它的性能不及如 greenDAO 这种编译型 ORM 框架。但它的易用性是一个方便的点——你可以在你的工作中综合考虑采用。如果你只是比较简单的数据存储,数据加载/保存时耗用的反射的那点性能对你的系统影响在可接受范围内,你可以考虑用 android-simple-ORM

2、使用方法

compile 'com.jungle.simpleorm:android-simple-ORM:1.0'

混淆 Proguard 配置如下:

-keep class * extends com.jungle.simpleorm.BaseEntity {*;}
-keepclassmembers class * extends com.jungle.simpleorm.BaseEntity {
    *;
}

3、接口

这里只展示部分接口,其他接口具体请参考代码。

接口 接口描述
createTable 创建表
drop 删除表
execSQL 执行 SQL 语句
queryPrimaryKeyList 查询某个表所有的主键(支持条件和约束)
querySum 查询某个字段的和(支持条件)
queryCount 查询个数(支持条件)
query、queryByPrimary、queryByCondition、queryByPosition 查询,返回结果的 List(支持条件、约束、LIMIT 等等)
remove、removeAll、removeByPrimaryKey 删除某个数据(支持条件)
insertNew 插入新数据(采用 insert 语句插入)
update 更新某个数据(采用 update 语句更新,支持条件)
replace 替换某个数据(采用 replace 语句替换)

4、表定义

表的定义比较简单,使用类似 POJO 的类定义即可。然后采用一些字段约束。约束用 Java 注解表述,具体列表如下:

注解 约束
ORMTable(tableName) 表名
PrimaryKey 主键
ForeignKey(clazz) 外键(将另一个 clazz 的主键作为外键)
CompositePrimaryKey 联合主键,通过注解一个类的多个字段,这些字段共同构成联合主键
AutoIncrement 自增字段
NotNull 类似于 “FIELD TEXT NOT NULL
DefaultNull(defValue) 类似于 “FIELD TEXT DEFAULT defValue
Unique 类似于 “FIELD TEXT UNIQUE
UniqueField 类似于 “CREATE TABLE tbl(..., UNIQUE(FIELD1, FIELD2, FIELD3))
NotColumnField 这个字段非表字段,将在 Load & Save 时忽略
UseParentFields 将使用父类的所有字段创建表,忽略本类的所有字段

5、BaseEntity 介绍

表定义类称为 Entity 实体,所有的 Entity 类均需派生自 com.jungle.simpleorm.BaseEntity。BaseEntity 有一些方法需要注意:

BaseEntity 方法 用途 & 含义
setNew、setStored、setRemoved 更改 Entity 的状态
reset 相当于 setNew
onPreLoad 在数据从数据库 Load 到 Entity 之前调用
onDataLoaded 在数据从数据库 Load 完成之后调用
onPreCommit 在数据将要写入数据库之前调用
onDataCommitted 在数据写入数据库之后调用
onDataUpdated 在调用 ORMSupporter.update 方法更新数据到数据库后调用
toRealEntity 在使用一系列 query 方法获取数据时调用,用于将本 Entity 转换为其他 Entity

6、ORMSupporter 使用示例

final int DB_VERSION = 1;
String dbFilePath = getDatabaseFilePath();

ORMSupporter supporter = new SQLiteORMSupporter(context, dbFilePath, DB_VERSION, new SimpleORMDatabaseListener() {

    @Override
    public void onCreated(ORMSupporter supporter, SQLiteDatabase db) {
        super.onCreated(supporter, db);

        // create table.
        supporter.createTable(GeneralAccountInfo.class);
    }

    @Override
    public void onUpgrade(ORMSupporter supporter, SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onUpgrade(supporter, db, oldVersion, newVersion);

        // drop unused table.
        supporter.drop(DownloadItem.class);

        // upgrade logic.
        if (oldVersion == 4 && newVersion == 5) {
            // ...
        }
    }
});


// load data
List<GeneralAccountInfo> accouns = supporter.query(GeneralAccountInfo.class);

List<GeneralAccountInfo> accouns = supporter.queryByCondition(
    GeneralAccountInfo.class, BaseEntity.and("id = 12458", "registerTime < 1477302247"));

// ...

7、表定义 & 使用示例

结合使用表字段的 UseParentFieldsBaseEntity.toRealEntity 方法,可以实现一些特殊效果。下面是一个例子:

/**
 * BaseMessage
 */
public class BaseMessage extends BaseEntity {

    public static class MessageType {
        public static final int ANY = 0;
        public static final int TEXT = 1;
        public static final int PICTURE = 2;
    }


    @PrimaryKey
    @AutoIncrement
    public long mMsgLocalId = INVALID_ID;

    @UniqueField
    public long mMsgGuid;

    public long mFromUid;
    public long mToUid;
    public int mMessageType = MessageType.ANY;
    public long mTimestamp;
    public byte[] mMsgContent;

    @NotColumnField
    public String mFromNickName;

    public BaseMessage() {
    }

    public BaseMessage(BaseMessage msg) {
        mMsgLocalId = msg.mMsgLocalId;
        // etc ...

        decodeMessage();
    }

    public void decodeMessage() {
    }

    @Override
    public BaseMessage toRealEntity() {
        switch (mMessageType) {
            case MessageType.TEXT:
                if (!(this instanceof TextMessage)) {
                    return new TextMessage(this);
                }
            case MessageType.PICTURE:
                if (!(this instanceof PictureMessage)) {
                    return new PictureMessage(this);
                }
            default:
                break;
        }

        return this;
    }

    @Override
    public String getTableName() {
        return getTableName(mToUid);
    }

    public static String getTableName(long toUid) {
        String prefix = "fake";
        return prefix + "_" + MiscUtils.generateMD5String(String.valueOf(toUid));
    }
}

我们定义了一个基础的聊天消息,而子消息类型有 TextMessagePictureMessage 多种。 消息体在 mMsgContent 这个字段里面。我们希望从数据库获取消息时,拿到的消息可以灵活转换为对应的 Java 对象。我们可以看出在 toRealEntity 方法里面,通过 mMessageType 做了转换。

子消息定义如下:

/*
 * TextMessage
 */
@UseParentFields
public class TextMessage extends BaseMessage {

    private String mText;

    public TextMessage() {
        // ...
    }

    public TextMessage(BaseMessage message) {
        super(message);
    }

    @Override
    public void decodeMessage() {
        try {
            PbMessage.Text text = PbMessage.Text.parseFrom(mMsgContent);
            mText = new String(text.getContent().toByteArray());
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
    }

    // ...
}

/*
 * TextMessage
 */
@UseParentFields
public class PictureMessage extends BaseMessage {

    public int mImageType;
    public int mImageWidth;
    public int mImageHeight;
    public int mImageSizeBytes;
    public String mImageThumbUrl;
    public String mImageUrl;

    public PictureMessage() {
        // ...
    }

    public PictureMessage(BaseMessage message) {
        super(message);
    }

    @Override
    public void decodeMessage() {
        // ...
    }
}

我们看到,子消息均用 UseParentFields 做了约束,表示在子消息写入数据库时,按父类 BaseMessage 进行反射写入,忽略子消息类的字段。使用如下:

ORMSupporter supporter = ...;

// query
long friendUid = 145701L;
String tableName = BaseMessage.getTableName(friendUid);
List<BaseMessage> messages = supporter.query(BaseMessage.class, tableName);

for (BaseMessage msg : messages) {
    if (msg instance TextMessage) {
        TextMessage text = (TextMessage) msg;
        // ...
    }
}

// create a new message
TextMessage msg = new TextMessage();
msg.mFromUid = friendUid;
msg.mMessageType = BaseMessage.MessageType.TEXT;
// fill other fields...
//

// save it to database
supporter.replace(msg);

License

/**
 * Android Simple ORM project.
 *
 * Copyright 2016 Arno Zhang <[email protected]>
 *
 * Date 2015/08/19
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

Releases

No releases published

Packages

No packages published

Languages