该博文为我本人亲测,代码编写过程中使用到了百度上很多大神的demo,如http://blog.csdn.net/shareye1992/article/details/50789216,http://blog.csdn.net/hedong_77/article/details/53167774,http://blog.csdn.net/wds1181977/article/details/51584052等博文。自己学习的同时也希望大家一起成长,第一次写自己的,博客希望大家能够谅解
当前android开发中常用的数据库框架有GreenDao、Ormlite、Realm等,这里本人仅就自己的对这三种数据库框架增、删、改、查四个方面运行速度上的性能进行对比,并附上相关代码。下面就这三个框架逐个分析。
GreenDAO是一个将对象映射到 SQLite 数据库中的轻量且快速ORM 解决方案。这里我所进行测试的GreenDao版本为greendao:1.3.7。详细测试demo流程如下:
(1)新建工程,并在src/main/java文件下新建package包javagen(这里不同于网上所说在java同级目录下建立java-gen)。
(2)配置 Android 工程(app)的 build.gradle,添加
sourceSets {
main {
java.srcDirs = ['src/main/java','src/main/java/javagen']
}
}
compile'de.greenrobot:greendao:1.3.7'
如图所示:
(1)通过 File -> New -> New Module -> JavaLibrary -> 填写相应的包名与类名 -> Finish.此处本人包名为daoexamplegenerator类名为ExampleDaoGenerator,完成后编写ExampleDaoGenerator类代码,具体如下:
public class ExampleDaoGenerator {
public static void main(String[] args) throws Exception {
//两个参数分别代表:数据库版本号与自动生成代码的包路径。
Schema schema = new Schema(1, "lzy.greendao");
addNote(schema);
// 最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录。
New DaoGenerator().generateAll(schema,"/software_forwork/androidstudio/MyProject/
DaoDemo/app/src/main/java/javagen");
}
private static void addNote(Schema schema) {
// 一个实体(类)就关联到数据库中的一张表,此处表名为「Note」(既类名)
Entity note = schema.addEntity("Note");
note.addIdProperty();
note.addStringProperty("text").notNull();
note.addStringProperty("comment");
}
}
执行 generator 工程,如一切正常,你将会在控制台看到如下日志,并且在主工程「java-gen」下会发现生成了DaoMaster、DaoSession、NoteDao、Note共4个类文件。此时文件结构如下图:
4.在MainActivity中进行测试,具体代码如下:
public class MainActivity extends AppCompatActivity {
private SQLiteDatabase db;
private DaoMaster daoMaster;
private DaoSession daoSession;
private Cursor cursor;
public static final String TAG = "DaoExample";
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupDatabase();
new Thread(new Runnable() {
@Override
public void run() {
deletetAll();
//addNote();
// search();
}
}
).start();
}
private void setupDatabase() {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
db = helper.getWritableDatabase();
// 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
}
private void search() { // Query 类代表了一个可以被重复执行的查询 Long before=Long.valueOf(System.currentTimeMillis()); System.out.println("查询之前的时间为:"+before); Listpublic void deletetAll () {list= getNoteDao().loadAll() ; System.out.println(list.get(9999).getText()+"***************************************"); Long after=Long.valueOf(System.currentTimeMillis()); System.out.println("查询之后的时间为:"+after); System.out.println("时间差为"+(after-before)+"毫秒"); }
}
private void addNote() String noteText = "小明"; String comment = "Added on "; // 插入操作,简单到只要你创建一个 Java 对象 Note note =null; Long before=Long.valueOf(System.currentTimeMillis()); System.out.println("存储之前的时间为:"+before); for(int i=0;i<10000;i++){ note=new Note(null,noteText+i,comment); getNoteDao().insert(note); note=null; } Long after=Long.valueOf(System.currentTimeMillis()); System.out.println("存储之后的时间为:"+after); System.out.println("时间差为"+(after-before)+"毫秒"); }
由上述代码在线程中依次调用增、查、删,效果如下图(分别对10000条数据、1000条数据进行增、查、删):
ORMLite是对象关系映射(Object Relational Mapping)数据库的一种轻量级SQL数据库的开发包(packages)。提供简单易用的DAO。首先需要下载相关jar包,本测试用的一个是ormlite-core-4.24.jar,另一个是ormlite-android-4.24.jar。
将下载好的jar包导入工程,并完成Bean的编写,此处bean与GreenDao测试中的bean一直,具体如下:
public class Note {
@DatabaseField(generatedId = true)
private int id;
@DatabaseField(index = true)
private Stringtext;
@DatabaseField(index = true)
private Stringcomment;
public Note() {
}
public Note(int id) {
this.id = id;}
public Note(int id, String text, String comment) {
this.id = id;
this.text= text;
this.comment= comment;}
public int getId() {
return id;}
public void setId(int id) {
this.id = id;}
public StringgetText() {
return text; }
public void setText(String text) {
this.text = text;}
public StringgetComment() {
return comment;}
public void setComment(String comment) {
this.comment = comment; }
}
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final String TABLE_NAME = "sqlite-test.db"; private Map, Dao> daos = new HashMap , Dao>(); private DatabaseHelper(Context context) { super(context, TABLE_NAME, null, 4); } @Override public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { try { TableUtils.createTable(connectionSource, Note.class); } catch (SQLException e) { e.printStackTrace(); } } @Override public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) { try { TableUtils.dropTable(connectionSource, Note.class, true); onCreate(database, connectionSource); } catch (SQLException e) { e.printStackTrace(); } } private static DatabaseHelper instance; public static synchronized DatabaseHelper getHelper(Context context) { context = context.getApplicationContext(); if (instance == null) { synchronized (DatabaseHelper.class) { if (instance == null) instance = new DatabaseHelper(context); } } return instance; } public synchronized Dao getDao(Class clazz) throws SQLException { Dao dao = null; String className = clazz.getSimpleName(); if (daos.containsKey(className)) { dao = daos.get(className); } if (dao == null) { dao = super.getDao(clazz); daos.put(className, dao); } return dao; } @Override public void close() { super.close(); for (String key : daos.keySet()) { Dao dao = daos.get(key); dao = null; } } }
public class NoteDao { private Context context; private Dao, Integer> userDaoOpe; private DatabaseHelper helper; public NoteDao(Context context) { this.context = context; try { helper = DatabaseHelper.getHelper(context); userDaoOpe = helper.getDao(Note.class); } catch (SQLException e) { e.printStackTrace(); } } public void add(Note user) { try { userDaoOpe.create(user); } catch (SQLException e) { e.printStackTrace(); } } public List findAll(){ List notes=null; try { notes = userDaoOpe.queryForAll(); } catch (SQLException e) { e.printStackTrace(); } return notes; } public void deleteAll( List notes){ try { userDaoOpe.delete(notes); } catch (SQLException e) { e.printStackTrace(); } } }
public class MainActivity extends AppCompatActivity { private NoteDao noteDao = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); noteDao = new NoteDao(this); new Thread(new Runnable() { @Override public void run() { addNote(); // Listnottt=search(); // delete(nottt); } }).start(); } public void addNote() { String noteText = "小明"; String comment = "Added on "; Note note = null; long before= Long.valueOf(System.currentTimeMillis()); System.out.println("存储之前的时间为:" +before); for (int i = 2; i < 10002; i++) { note = new Note(i, noteText + i, comment); noteDao.add(note); note = null; } long after= Long.valueOf(System.currentTimeMillis()); System.out.println("存储之后的时间为:" + after); System.out.println("插入10000条数据时间差为:" + (after-before)); } public Listsearch(){ long before= Long.valueOf(System.currentTimeMillis()); System.out.println("查询之前的时间为:" +before); List notes= noteDao.findAll(); long after= Long.valueOf(System.currentTimeMillis()); System.out.println("查询之后的时间为:" + after); System.out.println("查询10000条数据时间差为:" + (after-before)); return notes; } public void delete(Listnotess){ long before= Long.valueOf(System.currentTimeMillis()); System.out.println("删除之前的时间为:" +before); noteDao.deleteAll(notess);
long after= Long.valueOf(System.currentTimeMillis()); System.out.println("删除之后的时间为:" + after); System.out.println("删除10000条数据时间差为:" + (after-before)); } }
分别对10000条、1000条数据先后进行增、查、删操作,效果图如下:
数据库Realm,是用来替代sqlite的一种解决方案,它有一套自己的数据库存储引擎,比sqlite更轻量级,拥有更快的速度,并且具有很多现代数据库的特性,比如支持JSON,流式api,数据变更通知,自动数据同步,简单身份验证,访问控制,事件处理,最重要的是跨平台,目前已有Java,Objective C,Swift,React-Native,Xamarin这五种实现。本测试用的是realm-gradle-plugin:2.2.1"。
首先任然是添加依赖classpath"io.realm:realm-gradle-plugin:2.2.1",以及添加android配置apply plugin: 'realm-android'。再创建实体,继承RealmObject,如下所示:
public class Note extends RealmObject{
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@PrimaryKey
private int id;
private String text;
private String comment;
public Note() {
}
public Note(int id, String text, String comment) {
this.id = id;
this.text= text;
this.comment= comment;
}
public StringgetText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public StringgetComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
注意创建realm实例线程与使用Realm实例线程必须一致且初始化前必须调用Realm.init(Context xxx)。具体代码如下:
public RealmgetRealm(Context context)
{
byte[]key = new byte[64];
new SecureRandom().nextBytes(key);
Realm.init(context);
RealmConfiguration config = new RealmConfiguration.Builder()
.name("realmdb.realm") //文件名
.schemaVersion(0) //版本号
.deleteRealmIfMigrationNeeded()//声明版本冲突时自动删除原数据库(当调用了该方法时,上面的方法将失效)。
.build();//创建
return Realm.getInstance(config);
}
完整测试代码如下:
public class MainActivity extends AppCompatActivity{
Realm myRealm=null;
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyThread t1=new MyThread(this);
t1.start();
}
public Realm getRealm(Contextcontext)
{
byte[]key = new byte[64];
new SecureRandom().nextBytes(key);
Realm.init(context);
RealmConfiguration config = new RealmConfiguration.Builder()
.name("realmdb.realm") //文件名
.schemaVersion(0) //版本号
.deleteRealmIfMigrationNeeded()//声明版本冲突时自动删除原数据库(当调用了该方法时,上面的方法将失效)。
.build();//创建
return Realm.getInstance(config);
}
public void addNote(Realm realm){
Note book=null;
Longbefore=Long.valueOf(System.currentTimeMillis());
System.out.println("存储之前的时间为:"+before);
realm.beginTransaction();//必须先开启事务
for(int i=0;i<10000;i++){
book = new Note();
book.setText("司马迁1");
book.setComment("史记2");
book.setId(i);
realm.copyToRealmOrUpdate(book);
book=null;
}
realm.commitTransaction();//提交事务
Long after=Long.valueOf(System.currentTimeMillis());
System.out.println("存储之前的时间为:"+after);
System.out.println("存储10000条数据时间差为"+(after-before)+"毫秒");
/* Note book1 =realm.where(Note.class).equalTo("id", 5).findFirst();
if(book1==null){
System.out.println("*******************"+"--------------------------------");
}else {
System.out.println("*******************"+book1.getId());
}
*/
}
public RealmResults
Long before=Long.valueOf(System.currentTimeMillis());
System.out.println("查询之前的时间为:"+before);
RealmResults
Long after=Long.valueOf(System.currentTimeMillis());
System.out.println("查询之后的时间为:"+after);
System.out.println("查询10000条数据时间差为"+(after-before)+"毫秒");
System.out.println(dogs.get(9999).getId()+"--------------------------------------");
return dogs;
}
public void deletAll(RealmResults
Long before=Long.valueOf(System.currentTimeMillis());
System.out.println("删除之前的时间为:"+before);
realm.beginTransaction();
books.deleteAllFromRealm();
realm.commitTransaction();
Long after=Long.valueOf(System.currentTimeMillis());
System.out.println("删除之后的时间为:"+after);
System.out.println("删除10000条数据时间差为"+(after-before)+"毫秒");
}
class MyThreadextends Thread{
Context context;
public MyThread(){
super();
}
public MyThread(Context context){
super();
this.context=context;
}
public void run() {
myRealm=getRealm(context);
addNote(myRealm);
deletAll(searchNote(myRealm),myRealm);
}
};
}
由上述分别采用greendao、ormlite、realm三种数据框架对同一数据结构Note进行10000次和1000次的增、查、删操作,对比其各自的运行效率,其运行速度对比具体如下表所示(时间单位为毫秒):
数据库框架名 |
添加10000条数据时间 |
查询10000条数据时间 |
删除10000条数据时间 |
添加1000条数据时间 |
查询1000条数据时间 |
删除1000条数据时间 |
Greendao |
104666 |
600 |
47 |
11472 |
71 |
17 |
Ormlite |
140500 |
2463 |
269 |
13892 |
2671 |
283 |
Realm |
1597 |
8 |
136 |
327 |
4 |
29 |
上面数据仅表示在增、查、删操作时运行速度的快慢,其他性能、功能、未做对比,对比结果显著,不做详细赘。