Android 快速开发系列 ORMLite 框架最佳实践

标签: Android ORMLite
125685人阅读 评论(50) 收藏 举报
分类:

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39122981,本文出自【张鸿洋的博客】

上一篇已经对ORMLite框架做了简单的介绍:Android ORMLite 框架的入门用法~~本篇将介绍项目可能会使用到的一些用法,也为我们的使用ORMLite框架总结出一个较合理的用法。

通过上一篇的了解,我们使用ORMLite,需要自己写一个DatabaseHelper去继承OrmLiteSqliteOpenHelper,下面我们首先给出一个我认为比较靠谱的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项目中或多或少的都会使用数据库,为了提高我们的开发效率,当然少不了数据库ORM框架了,尤其是某些数据库操作特别频繁的app;本篇博客将详细介绍ORMLite的简易用法。下面开始介绍...
  • lmj623565791
  • lmj623565791
  • 2014-09-07 23:41:48
  • 83628

Android中使用OrmLite(二):复杂条件查询

在数据库中经常会使用到复杂的条件查询,来完成业务,下面学习下如何使用OrmLite进行复杂条件查询。...
  • industriously
  • industriously
  • 2016-03-03 20:58:56
  • 13177

ORMLite快速入门操作

大家在做安卓项目时肯定都会碰到数据库存储,原生的效率上会比较低,为了提高开发效率,大多公司会用一些框架,目前市面上比较流行的框架有ormlite、greenDao、SQLBrite、Realm等,其中...
  • CHX_W
  • CHX_W
  • 2017-11-22 16:32:16
  • 2080

ORMLite使用示例

ORMLite是一款优秀的轻量级的ORM框架,常用于Android平台,但它并不是 Android 平台专用的ORM框架,它也可用于普通的Java环境中。 ORMLite除了支持Sqlite外还支持M...
  • zffenger
  • zffenger
  • 2016-11-03 12:17:39
  • 850

OrmLite 轻量级ORM框架工具

前言 在项目中用到了sqlite这个的数据库。第一想法就是找个ORM框架进行操作,找到了OrmLite这个轻量级框架。 使用一下,感觉非常方便,就在此记录此框架。 整合到项目 普通项目 下载jar 放...
  • mingjie1212
  • mingjie1212
  • 2016-09-11 15:56:55
  • 1133

android OrmLite 入门

android OrmLite 入门android ormlite大家在开发中经常会用到数据库,但是数据库的操作其实挺繁琐的,为了方便我们的使用,所以我们来使用当下流行的orm框架进行数据库的操作,下...
  • ziqiang1
  • ziqiang1
  • 2016-08-04 18:12:16
  • 3068

Ormlite 介绍 一

概述            ORMlite是类似hibernate的对象映射框架,主要面向java语言,同时,是时下最流行的android面向数据库的的编程工具。 官方网站:http://orm...
  • sbvfhp
  • sbvfhp
  • 2014-03-04 14:28:17
  • 10906

OrmLite框架 —— OrmLite 入门使用(一)

OrmLite 三篇文章 OrmLite框架 —— OrmLite 入门使用(一) OrmLite框架 —— OrmLite 复杂条件查询(二) OrmLite框架 —— OrmLite 框架封装及使...
  • u013501637
  • u013501637
  • 2016-08-31 21:10:14
  • 1609

ORMLite学习入门笔记

使用原始的SQLiteHelper来操作维护数据库有点过于繁琐,重复工作量较大。所以会想到使用一个比较方便的ORM来维护我们本地的数据库,各位业界前辈都给我推荐了ORMLite(官网:http://o...
  • yzzst
  • yzzst
  • 2013-07-17 19:09:29
  • 12993

Android 数据库框架ormlite 使用精要

Android 数据库框架ormlite 使用精要前言本篇博客记录一下笔者在实际开发中使用到的一个数据库框架,这个可以让我们快速实现数据库操作,避免频繁手写sql,提高我们的开发效率,减少出错的机率。...
  • wwj_748
  • wwj_748
  • 2015-06-02 10:10:50
  • 11263
    个人资料
    专栏达人 博客之星
    等级:
    访问量: 1869万+
    积分: 5万+
    排名: 64
    博客专栏