你还在为数据库建表时那复杂而冗长的SQL语句烦恼么?
你还在为数据库存储时那频繁的put content values而感到焦躁么?
你还在为在数据库操作中只因为SQL语句中写错了一个字母而找了半天bug
而感到沮丧么?
快用GreenDao吧,解决以上各种疑难杂症,从此告别SQL语句。
回顾SQLiteDatabaseHelper
1.表的创建
如果你的数据库当中有20个数据模型,你要将以下面这段东西写20遍,还不带重样的- -。
If you type a wrong letter,loses the whole game
@Override
public void onCreate(SQLiteDatabase db) {
StringBuilder sb2 = new StringBuilder();
sb2.append("CREATE TABLE "+ TABLE_NAME+ "(")
.append("_id INTEGER PRIMARY KEY AUTOINCREMENT,")
.append("it TEXT,")
.append("is TEXT,")
.append("too TEXT,")
.append("painful TEXT,")
.append("do INTEGER,")
.append("you TEXT,")
.append("think BIGINT,")
.append("so INTEGER")
.append(");");
db.execSQL(sb2.toString());
}
2.数据库的存储操作
//以写入模式获取数据存储库
SQLiteDatabase db = mDbHelper.getWritableDatabase();
//创建一个新的值映射,其中列名称是键
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle);
//插入新行,返回新行的主键值
long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);
3.数据库的查询
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// 指定数据库中的哪些列
String[] projection = {FeedEntry._ID, FeedEntry.COLUMN_NAME_TITLE, FeedEntry.COLUMN_NAME_SUBTITLE };
// 过滤title值为 'My Title'的数据
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };
// 制定返回结果的排列顺序
String sortOrder = FeedEntry.COLUMN_NAME_SUBTITLE + " DESC";
Cursor c = db.query(FeedEntry.TABLE_NAME, // 你要查询的表
projection, // 要返回的列
selection, //定义的数据过滤规则
selectionArgs, // 过滤后返回的参数
null, // 不对行进行分组
null, //不按照行分的组过滤数据
sortOrder // 定义的排序规则 );
cursor.moveToFirst();
long itemId = cursor.getLong(cursor.getColumnIndexOrThrow(FeedEntry._ID));
4.数据库的删除
// 定义查询位置
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
// 制定要删除的参数(既title = 'MyTitle')
String[] selectionArgs = { "MyTitle" };
// 对应的删除操作
db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs)
5.数据库的更新
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// 定义要更新的值
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
//根据过滤调制定制要更新的列
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { "MyTitle" };
int count = db.update(FeedReaderDbHelper.FeedEntry.TABLE_NAME,values, selection,selectionArgs);
当然你也可以直接通过SQL语句进行相关操作
SQLiteDatabase db = mDbHelper.getReadableDatabase();
db.getReadableDatabase().execSQL(your sql?); //执行增删改查的SQL语句
GreenDao是什么?
一言以蔽之,greenDAO就是一个开源的Android ORM(对象关系映射)框架,使SQLite数据库的开发变得简单,便捷。而且在性能上greenDao也做了很大的优化。该文章主要是介绍如何使用greenDao。(毕竟该发挥拿来主义的时候就要发挥- -)
GreenDao的使用
1.Android Studio中的配置
① app目录下build.grandle的配置
dependencies依赖:
dependencies {
compile 'org.greenrobot:greendao:3.1.0'
}
在android的根下添加:
android {
greendao{
schemaVersion 1 //控制数据库版本,若数据库结构发生改变,更改此处版本号
targetGenDir 'src/main/java'
}
}
并在最上方添加对应的plugin
apply plugin: 'org.greenrobot.greendao'
② 工程根目录下目录下build.grandle的配置
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'org.greenrobot:greendao-gradle-plugin:3.1.0'
}
}
2.创建一张新的表
1.首先你要先创建一个新的类。并未类的属性标上对应的注解
@Entity代表你所要创建表的实体
@Id表示数据库的主键
@Property表示该实体里对应的属性(也就是字段)
@Entity
public class Singer {
@Id
private Long id; //主键
@Property
private String name;
@Property
private String sex;
@Property
private String country;
}
2.自动生成对应的DaoSession和DaoMater文件
之后双击 Build 一栏下的 Make Moudle app
编译完成后你会发现你的项目结构发生了如下变化:
我们回发现Studio自动帮我们生成了DaoMaster,DaoSession和Singer的实体操作类SingerDao。
3.GreenDao是如何工作的?
(此处只是简单的介绍一下GreenDao的工作原理,以及粗略的剖析一下源码,没兴趣的哥(姐)们儿直接可直接忽略此小节)
这里先简单的介绍一下这三个东西。
*** - DaoMaster***
greenDAO的入口点。 DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的DAO类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类OpenHelper和DevOpenHelper的底层依旧由SQLiteOpenHelper实现,在SQLite数据库中创建数据库,具体可以查看DaoMaster的源码。以下贴出部分源码。
/**DaoMaster源码**********************************/
public class DaoMaster extends AbstractDaoMaster {
//此处为数据库版本号
public static final int SCHEMA_VERSION = 1;
//此处也可自己定义一个类去继承OpenHelper
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}
}
public static abstract class OpenHelper extends DatabaseOpenHelper {
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
}
}
/*DatabaseOpenHelper 源码***********************************/
public abstract class DatabaseOpenHelper extends SQLiteOpenHelper{
public DatabaseOpenHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
this.context = context;
this.name = name;
this.version = version;
}
}
-DaoSession
管理特定模式的所有可用DAO对象,您可以使用其中一个getter方法获取它们。 DaoSession还为实体提供了一些通用的持久性方法,如插入,加载,更新,刷新和删除。以下为DaoSession源码
public class DaoSession extends AbstractDaoSession {
private final DaoConfig singerDaoConfig;
private final SingerDao singerDao;
public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
singerDaoConfig = daoConfigMap.get(SingerDao.class).clone();
singerDaoConfig.initIdentityScope(type);
//创建对应的DAO对象
singerDao = new SingerDao(singerDaoConfig, this);
//将DAO对象与Singer绑定起来
registerDao(Singer.class, singerDao);
}
/**获取对应的DAO对象*/
public SingerDao getSingerDao() {
return singerDao;
}
}
-SingerDao
这个我想不必过多介绍,相信接触过数据库操作的各位亲们都不会对它陌生,接下来让我们简单的看以它的部分代码。
public class SingerDao extends AbstractDao<Singer, Long> {
public static void createTable(Database db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + "\"SINGER\" (" + //
"\"_id\" INTEGER PRIMARY KEY ," + // 0: id
"\"NAME\" TEXT," + // 1: name
"\"SEX\" TEXT," + // 2: sex
"\"COUNTRY\" TEXT);"); // 3: country
}
}
我们会发现在这个类已经帮我们把表创建好了,关键是不需要你写一句SQL语句,你要想创建20张表的话只要写上20个数据模型并标上对应的属性值就可以了。这里会被DaoMaster调用。
public class DaoMaster extends AbstractDaoMaster {
public static void createAllTables(Database db, boolean ifNotExists) {
//此处调用
SingerDao.createTable(db, ifNotExists);
}
}
那他又是如何实现增删改查的呢?我们这里已增加数据为例,其余同理,可查看源码:
从SingerDao的源码我们可以看到它是继承自AbstractDao。我们来粗略的看一下内部进行了怎样实现的。
public abstract class AbstractDao<T, K> {
public long insert(T entity) {
return executeInsert(entity, statements.getInsertStatement(), true);
}
}
public class TableStatements {
public DatabaseStatement getInsertStatement() {
if (insertStatement == null) {
//sql语句的拼接
String sql = SqlUtils.createSqlInsert("INSERT INTO ", tablename, allColumns);
DatabaseStatement newInsertStatement = db.compileStatement(sql);
synchronized (this) {
if (insertStatement == null) {
insertStatement = newInsertStatement;
}
}
if (insertStatement != newInsertStatement) {
newInsertStatement.close();
}
}
return insertStatement;
}
}
public class SqlUtils {
public static String createSqlInsert(String insertInto, String tablename, String[] columns) {
StringBuilder builder = new StringBuilder(insertInto);
builder.append('"').append(tablename).append('"').append(" (");
appendColumns(builder, columns);
builder.append(") VALUES (");
appendPlaceholders(builder, columns.length);
builder.append(')');
return builder.toString();
}
}
我们会发现,到最后,他还是将所有的参数拼成了一句添加的sql。GreenDao的内部都已经帮你实现好了。而我们在外部只需要简单的调用一句即可。
singerDao.insert(new Singer(null, "周杰伦", "男", "中国"));
4.GreenDao的简单操作
①在Application中的配置
public class MyApplication extends Application {
public static final String TAG = MyApplication.class.getSimpleName();
private static Context mContext;
public SQLiteDatabase db;
public DaoSession daoSession;
public DaoMaster.DevOpenHelper helper;
public DaoMaster daoMaster;
@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
setupDatabase();
}
/**数据库的配置*/
private void setupDatabase() {
//此处的Helper可自定义
helper = new DaoMaster.DevOpenHelper(this, "green_dao_demo.db", null);
db = helper.getWritableDatabase();
// 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
}
public static Context getContext() {
return mContext;
}
public DaoSession getDaoSession() {
return daoSession;
}
public SQLiteDatabase getDb() {
return db;
}
}
②获取Dao对象
SingerDao singerDao = ((MyApplication) getActivity()
.getApplicationContext())
.getDaoSession()
.getSingerDao();
-添加数据
Singer singer = new Singer(null, name, age, country);
singerDao.insert(singer);
-查询数据
public List<Singer> getSingerList(String country) {
if (!TextUtils.isEmpty(country)) {
List<Singer> singers = getSingerDao()
.queryBuilder()
.where(SingerDao.Properties.Country.eq(country)) //判断条件
.orderDesc() //排序顺序
.build()
.list(); //生成对应的list
return singers;
}
return null;
}
-更新数据
//通过主键更新数据
singerDao.update(new Singer(Loing.valueOf(id),name, sex, country));
//常规更新
singer.setName(name);
singer.setSex(sex);
singer.setCountry(country);
singerDao.update(singer);
-删除数据
//通过主键删除
singerDao.deleteByKey(Long.valueOf(singer.getId()));
//常规删除
singerDao.delete(singer);
-批量操作
singerDao.insertInTx(singers); // 批量添加
singerDao.updateInTx(singers); // 批量更新
singerDao.deleteInTx(singers); //批量删除
项目示例地址
https://github.com/HandGrab/GreenDaoDemo
参考:
GreenDao官网:http://greenrobot.org/greendao/
GreenDao部分源码