上一篇已經對ORMLite框架作了簡單的介紹:Android ORMLite 框架的入門用法~~本篇將介紹項目可能會使用到的一些用法,也爲咱們的使用ORMLite框架總結出一個較合理的用法。java
經過上一篇的瞭解,咱們使用ORMLite,須要本身寫一個DatabaseHelper去繼承OrmLiteSqliteOpenHelper,下面咱們首先給出一個我認爲比較靠譜的Helper的寫法:android
[java] view plaincopysql
package com.zhy.zhy_ormlite.db; 數據庫
import java.sql.SQLException; app
import java.util.HashMap; 框架
import java.util.Map; ide
import android.content.Context; 測試
import android.database.sqlite.SQLiteDatabase; ui
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; this
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;
}
}
}
一、整個DatabaseHelper使用單例只對外公佈出一個對象,保證app中只存在一個SQLite Connection , 參考文章:http://www.touchlab.co/2011/10/single-sqlite-connection/
二、咱們對每一個Bean建立一個XXXDao來處理當前Bean的數據庫操做,固然真正去和數據庫打交道的對象,經過上面代碼中的getDao(T t)進行獲取
getDao爲一個泛型方法,會根據傳入Class對象進行建立Dao,而且使用一個Map來保持全部的Dao對象,只有第一次調用時纔會去調用底層的getDao()。
[java] view plaincopy
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:若是以爲不合理能夠留言指出,若是以爲不能接收,直接忽略。。。
如今咱們有兩張表一張User,一張Article;
Article中固然須要存儲User的主鍵,做爲關聯~~那麼在ORMLite中如何作到呢?
可能有人會直接在Article中聲明一個int類型userId屬性,看成普通屬性處理搞定,這種作法並無作,可是沒有體現出面向對象的思想。
面向對象是這樣的:Article屬於某個User
類這麼定義:
[java] view plaincopy
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類暫且就兩個屬性:
[java] view plaincopy
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
[java] view plaincopy
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;
}
}
接下來看咱們的測試類:
[java] view plaincopy
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屬性直接賦值呢?
兩種方式:
一、即上述寫法
[java] view plaincopy
article = articleDaoOpe.queryForId(id);
helper.getDao(User.class).refresh(article.getUser());
二、在user屬性的註解上:@DatabaseField(canBeNull = true, foreign = true, columnName = "user_id", foreignAutoRefresh = true)
添加foreignAutoRefresh =true,這樣;當調用queryForId時,拿到Article對象則直接攜帶了user;
每一個User關聯一個或多個Article,若是我在User中聲明一個Collection<Article> articles,我可否在查詢User的時候,一併可以獲取到articles的值呢?
答案是能夠的。在User中添加以下屬性,且註解以下:
@ForeignCollectionField
private Collection<Article> articles;
咱們在UserDao中書寫查詢User的代碼:
[java] view plaincopy
public User get(int id)
{
try
{
return userDaoOpe.queryForId(id);
} catch (SQLException e)
{
e.printStackTrace();
}
return null ;
}
測試代碼:
[java] view plaincopy
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());
}
}
輸出:
[java] view plaincopy
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;
上述代碼其實已經用到了簡單的條件查詢了:
一、簡單的where等於
articleDaoOpe.queryBuilder().where().eq("user_id", userId).query();直接返回Article的列表
二、where and
[java] view plaincopy
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' ;
三、更復雜的查詢
[java] view plaincopy
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' ) ;
好了,再複雜的查詢估計也可以湊出來了~~
使用queryBuilder是由於咱們但願執行完成查詢直接返回List<Bean>集合;
對於Update咱們並不關注返回值,直接使用
articleDaoOpe.updateRaw(statement, arguments);傳入sql和參數便可~~
何須在那articleDaoOpe.updateBuilder().updateColumnValue("name","zzz").where().eq("user_id", 1);這樣的痛苦呢~~~
同理還有deleteBuilder仍是建議直接拼寫sql,固然很簡單的除外,直接使用它的API~
在咱們的Dao中直接寫以下代碼:
[java] view plaincopy
//事務操做
TransactionManager.callInTransaction(helper.getConnectionSource(),
new Callable<Void>()
{
@Override
public Void call() throws Exception
{
return null;
}
});
一、當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會報錯,尼瑪,我以爲一點用沒有。。。
二、Join
[java] view plaincopy
QueryBuilder<Article, Integer> articleBuilder = articleDaoOpe
.queryBuilder();
QueryBuilder userBuilder = helper.getDao(User.class).queryBuilder();
articleBuilder.join(userBuilder);
Article與User作Join操做;
本篇主要想介紹在項目中如何寫DataBaseHelper已經如何寫BeanDao,以及列出了在項目中可能會用到的ORMLite的功能,若是須要詳細瞭解,還請看ORMLite官方文檔,源碼中也會提供~~