Android ORM数据库之OrmLite使用框架及源码分析
来源:互联网 发布:优化教育环境 编辑:程序博客网 时间:2024/05/18 09:07
一、简介
OrmLite是一个数据库框架,这个可以让我们快速实现数据库操作,避免频繁手写sql,提高我们的开发效率,减少出错的机率。
首先可以去它的官网看看www.ormlite.com,它的英文全称是Object Relational Mapping,意思是对象关系映射;如果接触过Java EE开发的,一定知道Java Web开发就有一个类似的数据库映射框架——Hibernate。简单来说,就是我们定义一个实体类,利用这个框架,它可以帮我们吧这个实体映射到我们的数据库中,在Android中是SQLite,数据中的字段就是我们定义实体的成员变量。
优点
1)轻量级
2)使用简单,易上手
3)封装完善
4)文档全面
缺点
1)基于反射,效率较低
2)缺少中文翻译文档
二、运用
1. 集成
首先到Ormlite官网下载Android的架包:http://ormlite.com/releases/。
可以看到,目前最新版本为4.49,对于Android的架包为: ormlite-android-4.48.jar 和 ormlite-core-4.48.jar。把两个jar拷贝到libs下,一般Gradle里面都会包含编译libs:
compile fileTree(dir: 'libs', include: ['*.jar'])
编译后就可以看到以上架包结构。
2.配置Bean类
数据库肯定离不开Bean类,先来看看我建的一个User类:
@DatabaseTable(tableName = "user")public class User { @DatabaseField(generatedId = true) private int id; @DatabaseField(columnName = "name") private String name; @DatabaseField(canBeNull = false, columnName = "desc") private String desc; /*关键啊,一定要加, 为每个class添加一个无参的构造器,并且构造器在包内是可见的*/ public User() {} public User(String name, String desc) { this.name = name; this.desc = desc; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; }}
首先在User类上添加@DatabaseTable(tableName = “user”),标明这是数据库中的一张表,标明为user;然后分别在属性上添加@DatabaseField(columnName = “name”) ,columnName的值为该字段在数据中的列名@DatabaseField(generatedId = true) ,generatedId 表示id为主键且自动生成,canBeNull表示该属性的内容不能为空,下面来介绍更多常用的属性设置:
3.封装Dao类
在普通Sqlite使用过程中,我们都会自己写个Helper类来继承SQLiteOpenHelper,然后里面封装一些方法来操作数据库,OrmLite也一样,但我们需要继承的是OrmLiteSqliteOpenHelper:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final String TABLE_NAME = "demo.db"; private static Context mApplicationContext; private static DatabaseHelper instance; private Map<String, Dao> daoMaps = new HashMap<>(); private DatabaseHelper(Context context) { super(context, TABLE_NAME, null, 2); } @Override public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { try { TableUtils.createTable(connectionSource, User.class); TableUtils.createTable(connectionSource, Article.class); } catch (SQLException e) { e.printStackTrace(); } } @Override public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) { try { TableUtils.dropTable(connectionSource, User.class, true); TableUtils.dropTable(connectionSource, Article.class, true); onCreate(database, connectionSource); } catch (SQLException e) { e.printStackTrace(); } } public static void initOrmLite(Context context) { mApplicationContext = context; getInstance(); } /** * 单例获取该Helper */ public static DatabaseHelper getInstance() { if (instance == null) { synInit(mApplicationContext); } return instance; } private synchronized static void synInit(Context context) { if (instance == null) { instance = new DatabaseHelper(context); } } /** * 获得Dao * * @return * @throws SQLException */ public synchronized Dao getDao(Class clazz) throws SQLException { Dao dao; String className = clazz.getSimpleName(); if (daoMaps.containsKey(className)) { dao = daoMaps.get(className); } else { dao = super.getDao(clazz); daoMaps.put(className, dao); } return dao; } /** * 释放资源 */ @Override public void close() { super.close(); for (String key : daoMaps.keySet()) { Dao dao = daoMaps.get(key); dao = null; } }}
这里需要实现两个方法:
创建表,我们直接使用ormlite提供的TableUtils.createTable(connectionSource, User.class);进行创建。
onCreate(SQLiteDatabase database,ConnectionSource connectionSource)
更新表:使用ormlite提供的TableUtils.dropTable(connectionSource, User.class, true);进行删除操作~
onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion)
我这里封装的是单例,所以一般最好在Application的OnCreate方法初始化:
DatabaseHelper.initOrmLite(this);
我看了很多人的写法,都喜欢在Helper里面写各种方法,获取各种Dao来操作数据库,要是应用数据复杂些,就会有很多很多的方法,复杂不容易管理,就像一个Activity写了几千行代码,让我是没兴趣去往下看方法,找方法也麻烦。所以我再这个Helper里面只写了个简单的getDao方法,通过传入是Bean类找到它对应的Dao类,然后只操作对应的Dao类,这样就做出了分离;而且可以发现我使用了一个Map将Dao存起来,做了个缓存。下面来看看我封装的Dao类代码:
public class UserDao { public static UserDao mUserDaoInstance; private Dao<User, Integer> mUserDao; public UserDao() { try { mUserDao = DatabaseHelper.getInstance().getDao(User.class); } catch (SQLException e) { e.printStackTrace(); } } public static UserDao getInstance() { if (mUserDaoInstance == null) { mUserDaoInstance = new UserDao(); } return mUserDaoInstance; } /** * 单条插入数据 */ public void insertUser(User user) { try { mUserDao.create(user); } catch (SQLException e) { e.printStackTrace(); } } /** * 多条插入数据 */ public void insertUsers(List<User> users) { try { mUserDao.create(users); } catch (SQLException e) { e.printStackTrace(); } } /** * 查询所有数据 */ public List<User> queryAllUser() { List<User> users = new ArrayList<>(); try { users = mUserDao.queryForAll(); } catch (SQLException e) { e.printStackTrace(); } return users; } /** * 通过id查询数据 */ public User queryUserById(int id) { User user = null; try { user = mUserDao.queryForId(id); } catch (SQLException e) { e.printStackTrace(); } return user; } /** * 删除该id的数据 */ public void deleteUserById(int id) { try { mUserDao.deleteById(id); } catch (SQLException e) { e.printStackTrace(); } } /** * 删除这些id的数据 */ public void deleteUserByIds(List<Integer> ids) { try { mUserDao.deleteIds(ids); } catch (SQLException e) { e.printStackTrace(); } } /** * 删除所有 */ public void deleteAllUser() { try { mUserDao.deleteBuilder().delete(); } catch (SQLException e) { e.printStackTrace(); } } /** * 更新当前实体类数据 */ public void updateUser(User user) { try { mUserDao.update(user); } catch (SQLException e) { e.printStackTrace(); } } /** * 更新当前数据的id */ public void updateUserById(User user, int id) { try { mUserDao.updateId(user, id); } catch (SQLException e) { e.printStackTrace(); } } /** * 自定义查询 */ public List<User> queryBy() throws SQLException { QueryBuilder<User, Integer> queryBuilder = mUserDao .queryBuilder(); Where<User, Integer> where = queryBuilder.where(); where.eq("id", 1); where.and(); where.eq("name", "xxx"); //或者 mUserDao.queryBuilder(). where(). eq("id", 1).and(). eq("name", "xxx"); return queryBuilder.query(); }}
我在这里也写成了单例模式,因为考虑到不止一个地方使用UserDao,使用代码如下:
User user = new User("jianglei", "金陵小霸王");UserDao.getInstance().insertUser(user);
其他的数据库操作同理,这样在维护一个数据库表的一些操作就比较简单了,在一个类里面维护,想找哪个数据库表的操作,就去对应类的Dao里面去找就行了。
看完OrmLite,大家可以再看看更简单,效率更高的GreenDao框架,我也整理好了,大家可以对比下:http://blog.csdn.net/qq_19711823/article/details/51837032
下面就是要讲比较枯燥的源码分析,没有兴趣的童鞋可以止步了。
三、源码分析
1.创建表
我们先来看看创建表的方法:
@Overridepublic void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { try { TableUtils.createTable(connectionSource, User.class); } catch (SQLException e) { e.printStackTrace(); }}
大家可以跟踪源码,可以发现,最主要的是doCreateTable中的两句话:
addCreateTableStatements(databaseType, tableInfo, statements, queriesAfter, ifNotExists);int stmtC = doStatements(connection, "create", statements, false, databaseType.isCreateTableReturnsNegative(), databaseType.isCreateTableReturnsZero());
先来看看addCreateTableStatements实现:
private static <T, ID> void addCreateTableStatements(DatabaseType databaseType, TableInfo<T, ID> tableInfo, List<String> statements, List<String> queriesAfter, boolean ifNotExists) throws SQLException { StringBuilder sb = new StringBuilder(256); sb.append("CREATE TABLE "); if(ifNotExists && databaseType.isCreateIfNotExistsSupported()) { sb.append("IF NOT EXISTS "); } databaseType.appendEscapedEntityName(sb, tableInfo.getTableName()); // 添加表名 sb.append(" ("); ArrayList additionalArgs = new ArrayList(); ArrayList statementsBefore = new ArrayList(); ArrayList statementsAfter = new ArrayList(); boolean first = true; FieldType[] i$ = tableInfo.getFieldTypes(); // 获取表的属性 int arg = i$.length; for(int i$1 = 0; i$1 < arg; ++i$1) { FieldType fieldType = i$[i$1]; if(!fieldType.isForeignCollection()) { if(first) { first = false; } else { sb.append(", "); // 第一个参数之前不需要“,” } String columnDefinition = fieldType.getColumnDefinition(); if(columnDefinition == null) { databaseType.appendColumnArg(tableInfo.getTableName(), sb, fieldType, additionalArgs, statementsBefore, statementsAfter, queriesAfter); } else { databaseType.appendEscapedEntityName(sb, fieldType.getColumnName()); sb.append(' ').append(columnDefinition).append(' '); // 添加列名 } } } databaseType.addPrimaryKeySql(tableInfo.getFieldTypes(), additionalArgs, statementsBefore, statementsAfter, queriesAfter); databaseType.addUniqueComboSql(tableInfo.getFieldTypes(), additionalArgs, statementsBefore, statementsAfter, queriesAfter); Iterator var16 = additionalArgs.iterator(); while(var16.hasNext()) { String var15 = (String)var16.next(); sb.append(", ").append(var15); } sb.append(") "); // 拼装结束 databaseType.appendCreateTableSuffix(sb); statements.addAll(statementsBefore); statements.add(sb.toString()); statements.addAll(statementsAfter); addCreateIndexStatements(databaseType, tableInfo, statements, ifNotExists, false); addCreateIndexStatements(databaseType, tableInfo, statements, ifNotExists, true); }
到这里,大家终于看到了一些熟悉的字眼,那些就是数据库最初的sql语句,这个函数主要是负责去生成我们要执行的sql语句。然后就是doStatements执行sql语句:
private static int doStatements(DatabaseConnection connection, String label, Collection<String> statements, boolean ignoreErrors, boolean returnsNegative, boolean expectingZero) throws SQLException { int stmtC = 0; for(Iterator i$ = statements.iterator(); i$.hasNext(); ++stmtC) { String statement = (String)i$.next(); int rowC = 0; CompiledStatement compiledStmt = null; compiledStmt = connection.compileStatement(statement, StatementType.EXECUTE, noFieldTypes, -1); rowC = compiledStmt.runExecute(); logger.info("executed {} table statement changed {} rows: {}", label, Integer.valueOf(rowC), statement); } ... return stmtC;}
- Android ORM数据库之OrmLite使用框架及源码分析
- Android ORM数据库之GreenDao使用教程及源码分析
- Android源码分析之仿OrmLite数据库框架
- 源码探索系列4---数据库ORM框架之Ormlite解析
- Android ORM框架之 ORMLite
- Android进阶之数据库框架ormlite使用
- Android项目使用ORMLite数据库框架 之 使用数据库配置文件
- android ORM框架ORMLite封装
- Android使用OrmLite数据库框架 之 使用表配置文件
- Android常用数据库ORM框架ORMlite和GreenDao比较
- Android ORM 框架之 Android中ORMLite应用基础
- Android使用OrmLite数据库框架 之 基本用法
- android 数据库使用之OrmLite
- Android ORM框架介绍之OrmLite注解与封装
- Android数据库ORM框架用法、源码和性能比较分析
- OrmLite数据库框架的集成及使用
- Android 数据库框架ormlite 使用精要
- Android 数据库框架ormlite 使用精要
- VMWare虚拟机设置固定ip上网方法
- EditText详细介绍
- Linux 挂载 windows共享盘
- 安装Nginx
- 使用git pull文件时和本地文件冲突怎么办
- Android ORM数据库之OrmLite使用框架及源码分析
- 【剑指offer】替换空格
- iOS报错汇总
- Mybatis中模糊查询的各种写法
- UGUI如何在UI与UI直接穿插粒子特效和模型
- jzoj 1417. 【2012.04.14普及组】最短路线
- 3.JVM之class文件校验器
- 【HDU 1180】诡异的楼梯(BFS)
- Python入门语法要点