前面說了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