Android 快速开发系列 ORMLite 框架最佳实践
比较靠谱的Helper的写法:
1、DatabaseHelper
- package com.zhy.zhy_ormlite.db;
- import java.sql.SQLException;
- import java.util.HashMap;
- import java.util.Map;
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
- import com.j256.ormlite.dao.Dao;
- import com.j256.ormlite.support.ConnectionSource;
- import com.j256.ormlite.table.TableUtils;
- import com.zhy.zhy_ormlite.bean.Article;
- import com.zhy.zhy_ormlite.bean.Student;
- import com.zhy.zhy_ormlite.bean.User;
- public class DatabaseHelper extends OrmLiteSqliteOpenHelper
- {
- private static final String TABLE_NAME = "sqlite-test.db";
- private Map<String, Dao> daos = new HashMap<String, Dao>();
- private DatabaseHelper(Context context)
- {
- super(context, TABLE_NAME, null, 4);
- }
- @Override
- public void onCreate(SQLiteDatabase database,
- ConnectionSource connectionSource)
- {
- try
- {
- TableUtils.createTable(connectionSource, User.class);
- TableUtils.createTable(connectionSource, Article.class);
- TableUtils.createTable(connectionSource, Student.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);
- TableUtils.dropTable(connectionSource, Student.class, true);
- onCreate(database, connectionSource);
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- }
- private static DatabaseHelper instance;
- /**
- * 单例获取该Helper
- *
- * @param context
- * @return
- */
- 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;
- }
- }
- }
1、整个DatabaseHelper使用单例只对外公布出一个对象,保证app中只存在一个SQLite Connection , 参考文章:http://www.touchlab.co/2011/10/single-sqlite-connection/
2、我们对每个Bean创建一个XXXDao来处理当前Bean的数据库操作,当然真正去和数据库打交道的对象,通过上面代码中的getDao(T t)进行获取
getDao为一个泛型方法,会根据传入Class对象进行创建Dao,并且使用一个Map来保持所有的Dao对象,只有第一次调用时才会去调用底层的getDao()。
2、Bean的Dao
- package com.zhy.zhy_ormlite.db;
- import java.sql.SQLException;
- import android.content.Context;
- import com.j256.ormlite.dao.Dao;
- import com.zhy.zhy_ormlite.bean.User;
- public class UserDao
- {
- private Context context;
- private Dao<User, Integer> userDaoOpe;
- private DatabaseHelper helper;
- public UserDao(Context context)
- {
- this.context = context;
- try
- {
- helper = DatabaseHelper.getHelper(context);
- userDaoOpe = helper.getDao(User.class);
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- }
- /**
- * 增加一个用户
- * @param user
- */
- public void add(User user)
- {
- try
- {
- userDaoOpe.create(user);
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- }//...other operations
- }
我们的所有的XXXDao遵循以上的风格~
好了,基本了解了我们的代码的结构~~ps:如果觉得不合理可以留言指出,如果觉得不能接收,直接忽略。。。
3、ORMLite外键引用
现在我们有两张表一张User,一张Article;
Article中当然需要存储User的主键,作为关联~~那么在ORMLite中如何做到呢?
可能有人会直接在Article中声明一个int类型userId属性,当作普通属性处理搞定,这种做法并没有做,但是没有体现出面向对象的思想。
面向对象是这样的:Article属于某个User
类这么定义:
- package com.zhy.zhy_ormlite.bean;
- import com.j256.ormlite.field.DatabaseField;
- import com.j256.ormlite.table.DatabaseTable;
- @DatabaseTable(tableName = "tb_article")
- public class Article
- {
- @DatabaseField(generatedId = true)
- private int id;
- @DatabaseField
- private String title;
- @DatabaseField(canBeNull = true, foreign = true, columnName = "user_id")
- private User user;
- public int getId()
- {
- return id;
- }
- public void setId(int id)
- {
- this.id = id;
- }
- public String getTitle()
- {
- return title;
- }
- public void setTitle(String title)
- {
- this.title = title;
- }
- public User getUser()
- {
- return user;
- }
- public void setUser(User user)
- {
- this.user = user;
- }
- @Override
- public String toString()
- {
- return "Article [id=" + id + ", title=" + title + ", user=" + user
- + "]";
- }
- }
不会去定义一个int类型的userId,而是直接定义一个User成员变量,表示本Article属于该User;
然后在User user属性上添加: @DatabaseField(canBeNull = true, foreign = true, columnName = "user_id")
canBeNull -表示不能为null;foreign=true表示是一个外键;columnName 列名
User类暂且就两个属性:
- package com.zhy.zhy_ormlite.bean;
- import com.j256.ormlite.field.DatabaseField;
- import com.j256.ormlite.table.DatabaseTable;
- @DatabaseTable(tableName = "tb_user")
- public class User
- {
- @DatabaseField(generatedId = true)
- private int id;
- @DatabaseField(columnName = "name")
- private String name;
- public User()
- {
- }
- 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;
- }
- @Override
- public String toString()
- {
- return "User [id=" + id + ", name=" + name
- + "]";
- }
- }
现在看我们的ArticleDao
- package com.zhy.zhy_ormlite.db;
- import java.sql.SQLException;
- import java.util.List;
- import android.content.Context;
- import com.j256.ormlite.dao.Dao;
- import com.zhy.zhy_ormlite.bean.Article;
- import com.zhy.zhy_ormlite.bean.User;
- public class ArticleDao
- {
- private Dao<Article, Integer> articleDaoOpe;
- private DatabaseHelper helper;
- @SuppressWarnings("unchecked")
- public ArticleDao(Context context)
- {
- try
- {
- helper = DatabaseHelper.getHelper(context);
- articleDaoOpe = helper.getDao(Article.class);
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- }
- /**
- * 添加一个Article
- * @param article
- */
- public void add(Article article)
- {
- try
- {
- articleDaoOpe.create(article);
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- }
- /**
- * 通过Id得到一个Article
- * @param id
- * @return
- */
- @SuppressWarnings("unchecked")
- public Article getArticleWithUser(int id)
- {
- Article article = null;
- try
- {
- article = articleDaoOpe.queryForId(id);
- helper.getDao(User.class).refresh(article.getUser());
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- return article;
- }
- /**
- * 通过Id得到一篇文章
- * @param id
- * @return
- */
- public Article get(int id)
- {
- Article article = null;
- try
- {
- article = articleDaoOpe.queryForId(id);
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- return article;
- }
- /**
- * 通过UserId获取所有的文章
- * @param userId
- * @return
- */
- public List<Article> listByUserId(int userId)
- {
- try
- {
- return articleDaoOpe.queryBuilder().where().eq("user_id", userId)
- .query();
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- return null;
- }
- }
接下来看我们的测试类:
- public class OrmLiteDbTest extends AndroidTestCase
- {
- public void testAddArticle()
- {
- User u = new User();
- u.setName("张鸿洋");
- new UserDao(getContext()).add(u);
- Article article = new Article();
- article.setTitle("ORMLite的使用");
- article.setUser(u);
- new ArticleDao(getContext()).add(article);
- }
- public void testGetArticleById()
- {
- Article article = new ArticleDao(getContext()).get(1);
- L.e(article.getUser() + " , " + article.getTitle());
- }
- public void testGetArticleWithUser()
- {
- Article article = new ArticleDao(getContext()).getArticleWithUser(1);
- L.e(article.getUser() + " , " + article.getTitle());
- }
- public void testListArticlesByUserId()
- {
- List<Article> articles = new ArticleDao(getContext()).listByUserId(1);
- L.e(articles.toString());
- }
分别测试,添加一个Article;通过Id获取一个Article;通过Id获取一个Article且携带User;通过userId获取所有的Article;
主要看第三个:通过Id获取一个Article且携带User,testGetArticleWithUser(id)
如何值传一个Article的Id,然后能够拿到Article对象,且内部的user属性直接赋值呢?
两种方式:
1、即上述写法
- article = articleDaoOpe.queryForId(id);
- helper.getDao(User.class).refresh(article.getUser());
2、在user属性的注解上:@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id", foreignAutoRefresh = true)
添加foreignAutoRefresh =true,这样;当调用queryForId时,拿到Article对象则直接携带了user;
4、关联一个集合
每个User关联一个或多个Article,如果我在User中声明一个Collection<Article> articles,我能否在查询User的时候,一并能够获取到articles的值呢?
答案是可以的。在User中添加如下属性,且注解如下:
@ForeignCollectionField
private Collection<Article> articles;
我们在UserDao中书写查询User的代码:
- public User get(int id)
- {
- try
- {
- return userDaoOpe.queryForId(id);
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- return null ;
- }
测试代码:
- public void testGetUserById()
- {
- User user = new UserDao(getContext()).get(1);
- L.e(user.getName());
- if (user.getArticles() != null)
- for (Article article : user.getArticles())
- {
- L.e(article.toString());
- }
- }
输出:
- 09-07 22:49:06.484: E/zhy(7293): 张鸿洋
- 09-07 22:49:06.484: E/zhy(7293): Article [id=1, title=ORMLite的使用]
可以看到,我们通过一个queryForId,成功的获取了User,以及User关联的所有的Articles;
5、条件查询QueryBuilder的使用
上述代码其实已经用到了简单的条件查询了:
1、简单的where等于
articleDaoOpe.queryBuilder().where().eq("user_id", userId).query();直接返回Article的列表
2、where and
- QueryBuilder<Article, Integer> queryBuilder = articleDaoOpe
- .queryBuilder();
- Where<Article, Integer> where = queryBuilder.where();
- where.eq("user_id", 1);
- where.and();
- where.eq("name", "xxx");
- //或者
- articleDaoOpe.queryBuilder().//
- where().//
- eq("user_id", 1).and().//
- eq("name", "xxx");
上述两种都相当与:select * from tb_article where user_id = 1 and name = 'xxx' ;
3、更复杂的查询
- where.or(
- //
- where.and(//
- where.eq("user_id", 1), where.eq("name", "xxx")),
- where.and(//
- where.eq("user_id", 2), where.eq("name", "yyy")));
select * from tb_article where ( user_id = 1 and name = 'xxx' ) or ( user_id = 2 and name = 'yyy' ) ;
好了,再复杂的查询估计也能够凑出来了~~
6、updateBuilder、deleteBuilder
使用queryBuilder是因为我们希望执行完成查询直接返回List<Bean>集合;
对于Update我们并不关注返回值,直接使用
articleDaoOpe.updateRaw(statement, arguments);传入sql和参数即可~~
何必在那articleDaoOpe.updateBuilder().updateColumnValue("name","zzz").where().eq("user_id", 1);这样的痛苦呢~~~
同理还有deleteBuilder还是建议直接拼写sql,当然很简单的除外,直接使用它的API~
7、事务操作
在我们的Dao中直接写如下代码:
- //事务操作
- TransactionManager.callInTransaction(helper.getConnectionSource(),
- new Callable<Void>()
- {
- @Override
- public Void call() throws Exception
- {
- return null;
- }
- });
8、其他操作
1、当Bean继承BaseDaoEnabled时,可以使用bean.create(bean);bean.update(bean)一类操作
例如:
Student extends BaseDaoEnabled<Student, Integer>
Dao dao = DatabaseHelper.getHelper(getContext()).getDao(Student.class);
Student student = new Student();
student.setDao(dao);
student.setName("张鸿洋");
student.create();
前提dao需要手动设置,如果dao为null会报错,尼玛,我觉得一点用没有。。。
2、Join
- QueryBuilder<Article, Integer> articleBuilder = articleDaoOpe
- .queryBuilder();
- QueryBuilder userBuilder = helper.getDao(User.class).queryBuilder();
- articleBuilder.join(userBuilder);
Article与User做Join操作;
本篇主要想介绍在项目中如何写DataBaseHelper已经如何写BeanDao,以及列出了在项目中可能会用到的ORMLite的功能,如果需要详细了解,还请看ORMLite官方文档,源码中也会提供~~
Android 快速开发系列 ORMLite 框架最佳实践的更多相关文章
- Android 快速开发系列 ORMLite 框架最佳实践之实现历史记录搜索
首先在build.gald中添加compile 'com.j256.ormlite:ormlite-android:4.48'的引用 compile 'com.j256.ormlite:ormlite ...
- Android 快速开发系列 打造万能的ListView GridView 适配器
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38902805 ,本文出自[张鸿洋的博客] 1.概述 相信做Android开发的写 ...
- Android快速开发系列 10个常用工具类
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38965311,本文出自[张鸿洋的博客] 打开大家手上的项目,基本都会有一大批的辅 ...
- 【转】 Android快速开发系列 10个常用工具类 -- 不错
原文网址:http://blog.csdn.net/lmj623565791/article/details/38965311 转载请标明出处:http://blog.csdn.net/lmj6235 ...
- [ 转]Android快速开发–使用ORMLite操作数据库
OrmLite是一个数据库操作辅助的开源框架,主要面向Java语言.在Android面向数据库开发中,是一个比较流行的开源框架,方便操作而且功能强大,今天来学习一下,最近的项目中也有所涉及,写个博客来 ...
- 快速接入 Android BLE 开发的基础框架
代码地址如下:http://www.demodashi.com/demo/12092.html ** Android BLE基础操作框架,基于回调,操作简单.包含扫描.多连接.广播包解析.服务读写及通 ...
- 封装一个简单好用的打印Log的工具类And快速开发系列 10个常用工具类
快速开发系列 10个常用工具类 http://blog.csdn.net/lmj623565791/article/details/38965311 ------------------------- ...
- Android商城开发系列(四)——butterknife的使用
在上一篇博客:Android商城开发系列(三)——使用Fragment+RadioButton实现商城底部导航栏实现商城的底部导航栏时,里面用到了butterknife,今天来讲解一下的butterk ...
- 快速入门系列--WebAPI--03框架你值得拥有
接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI ...
随机推荐
- 在LINUX上创建GIT服务器
转载 如果使用git的人数较少,可以使用下面的步骤快速部署一个git服务器环境. 1. 生成 SSH 公钥 每个需要使用git服务器的工程师,自己需要生成一个ssh公钥进入自己的~/.ssh目录,看有 ...
- CSS的兼容性与BUG处理
骨灰级清除浮动 .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility ...
- hibernate注解的简单应用
注解代替了我们用的*.hbm.xml文件.简少了我们的代码量:应用简单. @Override 用途:重写父类的同名方法 单元测试注解 @Test 用途:用于测试 @Before 用途:单测方法走之前执 ...
- CentOS下WDCP下的MYSQL开启远程连接
1.首先要在防火墙开启3306端口访问 2.然后做如下操作 如何开启MySQL的远程帐号-1)首先以 root 帐户登陆 MySQL 在 Windows 主机中点击开始菜单,运行,输入"cm ...
- JavaScript中国象棋程序(7) - 置换表
"JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第2节. 这一系列共有9个部分: 0.JavaScript中国象 ...
- 复制vmware中的centos后无法上网问题
复制vmware中的centos后无法上网问题 查看IP命令 ip addr 网卡信息 eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000 使用的是e ...
- BZOJ1115:[POI2009]石子游戏Kam(博弈论)
挺水的 听说是阶梯nim和,就去看了一下,然后就会了= = 观察题目,发现拿第i堆棋子k个造成的影响就是第i+1堆棋子能多拿k个 可以把模型转化为,有n堆石子,每次从某一堆拿一个石子,放在下一堆中,不 ...
- Jsp——response对象
<%@ page language="java" contentType="text/html; charset=UTF-8" import=" ...
- 【Scala】Scala之Methods
一.前言 前面学习了Scala的Class,下面接着学习Method(方法). 二.Method Scala的方法与Java的方法类似,都是添加至类中的行为,但是在具体的实现细节上差异很大,下面展示一 ...
- PHP链接Redis
命令行下运行 redis-server.exe redis.windows.conf 此时,redis服务已经开启,然后我们可以再新开一个命令行,作为控制台 redis-cli.exe -h 127. ...