前面说了OrmLite的基本使用,现在说下更规范的做法以及常用的一些功能。
1.DatabaseHelper
package com.example.ormlite.db; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import com.example.ormlite.bean.Article; import com.example.ormlite.bean.User; 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; /** * 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()。 * @author Administrator * */ public class DatabaseHelperTwo extends OrmLiteSqliteOpenHelper{ private static final String TABLE_NAME="sqlite-test.db"; private static DatabaseHelperTwo instance; private Map<String,Dao> daos=new HashMap<String,Dao>(); public DatabaseHelperTwo(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(); } } /** * 单例获取该Helper * @param context * @return */ public static synchronized DatabaseHelperTwo getHelper(Context context){ context=context.getApplicationContext(); if(instance==null){ synchronized(DatabaseHelperTwo.class){ if(instance==null){ instance=new DatabaseHelperTwo(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; } } }
2.编写Dao类
package com.example.ormlite.dao; import java.sql.SQLException; import com.example.ormlite.bean.User; import com.example.ormlite.db.DatabaseHelperTwo; import com.j256.ormlite.dao.Dao; import android.content.Context; public class UserDaoTwo { private Context context; private Dao<User,Integer> userDaoImpl; private DatabaseHelperTwo helper; @SuppressWarnings("unchecked") public UserDaoTwo(Context context){ this.context=context; try { helper=DatabaseHelperTwo.getHelper(context); userDaoImpl=helper.getDao(User.class); } catch (SQLException e) { e.printStackTrace(); } } public void add(User user){ try { userDaoImpl.create(user); } catch (SQLException e) { e.printStackTrace(); } } //......other operations }
3.外键引用
package com.example.ormlite.bean; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; /** * ORMLite外键引用 * 需求:两个表User,Article,其中Article中需要存储User的主键作为关联,在ORMLite中如何实现? * 直接在Article中声明一个Int类型userId属性,当作普通属性处理搞定,也是可行的。但是并没有体现面向对象的思想。 * 可按如下实现: * 1.不去定义一个int类型的userId,而是直接定义一个User成员变量,表示本Article属于该User。 * 2.在User user属性上添加:@DatabaseField(canBeNull=true,foreign=true,columnName="user_id") * canBeNull--表示不能为null;foreign=true表示一个外键;columnName列名 * @author Administrator * */ @DatabaseTable(tableName="tb_article") public class Article { @DatabaseField(generatedId=true) private int id; @DatabaseField(columnName="title") private String title; @DatabaseField(canBeNull=true,foreign=true,columnName="user_id") private User user; public Article() { super(); // TODO Auto-generated constructor stub } public Article(String title, User user) { super(); this.title = title; this.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 + "]"; } }
接下来编写ArticleDao:
package com.example.ormlite.dao; import java.sql.SQLException; import java.util.List; import android.content.Context; import com.example.ormlite.bean.Article; import com.example.ormlite.bean.User; import com.example.ormlite.db.DatabaseHelperTwo; import com.j256.ormlite.dao.Dao; public class ArticleDao { private Dao<Article,Integer> articleDaoImpl; private DatabaseHelperTwo helper; @SuppressWarnings("unchecked") public ArticleDao(Context context){ helper=DatabaseHelperTwo.getHelper(context); try { articleDaoImpl=helper.getDao(Article.class); } catch (SQLException e) { e.printStackTrace(); } } /** * 添加 * @param article */ public void add(Article article){ try { articleDaoImpl.create(article); } catch (SQLException e) { e.printStackTrace(); } } /** * 通过Id得到一个Article * @param id * @return */ @SuppressWarnings("unchecked") public Article getArticleWithUser(int id){ Article article=null; try { article=articleDaoImpl.queryForId(id); //如何做到只传一个Article的id,然后能够拿到Article对象,且内部的user属性直接赋值? //方式1 helper.getDao(User.class).refresh(article.getUser()); //方式2 //在user属性的注解上:@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id", foreignAutoRefresh = true) //foreignAutoRefresh =true,当调用queryForId时,拿到Article对象则直接携带了user } catch (SQLException e) { e.printStackTrace(); } return article; } /** * 通过Id得到一片文章 * @param id * @return */ public Article getArticleById(int id){ Article article=null; try { article=articleDaoImpl.queryForId(id); } catch (SQLException e) { e.printStackTrace(); } return article; } public List<Article> getArticleListByUserId(int userId){ try { return articleDaoImpl.queryBuilder().where().eq("user_id", userId).query(); } catch (SQLException e) { e.printStackTrace(); } return null; } }
测试:
package com.example.ormlite.test; import java.util.List; import android.test.AndroidTestCase; import android.util.Log; import com.example.ormlite.bean.Article; import com.example.ormlite.bean.User; import com.example.ormlite.dao.ArticleDao; import com.example.ormlite.dao.UserDao; import com.example.ormlite.dao.UserDaoTwo; public class OrmLiteDbTestTwo extends AndroidTestCase{ public void AddArticle(){ User u=new User(); u.setName("yq"); u.setDesc("developer"); 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()).getArticleById(1); Log.i("OrmLiteDbTestTwo", article.getUser().toString() + " , " + article.getTitle()); } /** * 通过id获取一个携带User的Article */ public void testGetArticleWithUser(){ Article article = new ArticleDao(getContext()).getArticleWithUser(1); Log.i("OrmLiteDbTestTwo", article.getUser().toString() + " , " + article.getTitle()); } public void testSGetArticleListByUserId(){ List<Article> articles =new ArticleDao(getContext()).getArticleListByUserId(1); Log.i("OrmLiteDbTestTwo", articles.toString()); } }
4.关联一个集合
每个User关联一个或多个Article,如果在User中声明一个Collection<Article> articles,可否做到在查询User的时候一并能够获取到articles的值?
是可以的。在User中加属性:
@ForeignCollectionField private Collection<Article> articles;
UserDao中加方法:
public User getUserById(int id){ try { return userDaoImpl.queryForId(id); } catch (SQLException e) { e.printStackTrace(); } return null; }
测试中加方法:
public void testGetUserById(){ User user=new UserDaoTwo(getContext()).getUserById(2); Log.i("OrmLiteDbTestTwo", user.getName()); if(user.getArticles()!=null){ for (Article article : user.getArticles()) { Log.i("OrmLiteDbTestTwo", article.toString()); } } }
5.查询条件QueryBuilder的使用
(1)简单的where等于
articleDaoImpl.queryBuilder().where().eq("user_id", userId).query(); //返回Article的列表
(2)where and
QueryBuilder<Article, Integer> queryBuilder=articleDaoImpl.queryBuilder(); Where<Article, Integer> where=queryBuilder.where(); where.eq("user_id", 2); where.and(); where.eq("name", "xxx"); //或者 articleDaoImpl.queryBuilder().where().eq("user_id", userId).and().eq("name", "xxx");
上述的两种方法都相当于:select * from tb_article where user_id = 2 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我们并不关注返回值,可以直接用articleDaoImpl.updateRaw(statement, arguments);传入sql和参数即可。也就没必要去用
articleDaoImpl.updateBuilder().updateColumnValue("name","zzz").where().eq("user_id", 1);这么痛苦了。
同理,deleteBuilder也建议直接瓶邪sql,当然很简单的除外。
7.事务
在Dao中直接写如下代码:
TransactionManager.callInTransaction(helper.getConnectionSource(), new Callable<Void>() { @Override public Void call() throws Exception { return null; } });
8.其他操作
1.当Bean继承BaseDaoEnable时,可以使用bean.create(bean); bean.update(bean)一类操作
例如:
package com.example.ormlite.bean; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.misc.BaseDaoEnabled; import com.j256.ormlite.table.DatabaseTable; @DatabaseTable(tableName = "tb_student") public class Student extends BaseDaoEnabled<Student, Integer> { @DatabaseField(generatedId = true) private int id; @DatabaseField private String name; public Student(){ } 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; } }
Dao dao=DatabaseHelperTwo.getHelper(context).getDao(Student.class); Student stu=new Student(); stu.setDao(dao); stu.setName("qq"); stu.create();
前提是dao需要手动设置,如果dao为null会报错。
2.Join
Article与User做Join操作:
QueryBuilder<Article, Integer> articleBuilder = articleDaoImpl.queryBuilder(); QueryBuilder userBuilder = helper.getDao(User.class).queryBuilder(); articleBuilder.join(userBuilder);
其他具体的查看官方文档。
源码下载:http://pan.baidu.com/s/1ntMX99n 提取码:jri5