android Sqlite操作之-- 自定义ORM关系实体映射类

任何android应用程序都少不了数据库的操作,即使是客户端程序也会有一些特定的数据存入到数据库中,例如:用户浏览记录,收藏列表等等,所以数据库的操作就是一个会很频繁使用的操作,所以对这个部分的封装就很有必要了,Web端有Hibernate等一系列优秀的框架,虽然android应用程序在git上也有一些开源的OOM框架,但总觉得还是没必要引入第三方的东西,于是就自己封装了一个数据库操作类,只要调用此类相应的方法,传入要保存的实体对象或更新的实体对象即可,查询也是同样的,只要传入查询条件和Class,就返回对应的实体对象,这样只要我们进行一次封装,以后就可以直接用这个类去操作数据库,而不必每次都写繁杂的sql语句.下面就是我封装类的部分代码:

import com.micen.buyers.module.db.Module;

/**********************************************************
 * @文件名称:DBDataHelper.java
 * @创建时间:2014-2-10 下午02:41:51
 * @文件描述:数据库操作助手类
 * @修改历史:2014-2-10创建初始版本
 **********************************************************/
public final class DBDataHelper
{
	private static DBDataHelper dataHelper = null;
	private DBHelper dbHelper = null;
	private static final String SELECT = "select ";
	private static final String FROM = " from ";
	private static final String WHERE = " where ";
	private static final String ORDER_BY = " order by ";

	private DBDataHelper()
	{
		dbHelper = DBHelper.getInstance();
	}

	public static DBDataHelper getInstance()
	{
		if (dataHelper == null)
		{
			dataHelper = new DBDataHelper();
		}
		return dataHelper;
	}

	/**
	 * 根据条件查询数据库表
	 * @param tableName
	 * @param showColumns
	 * @param selection
	 * @param selectionArgs
	 * @param orderBy
	 * @param cls
	 * @return
	 */
	public ArrayList<Module> select(String tableName, String showColumns, String selection, String selectionArgs,
			String orderBy, Class<?> cls)
	{
		synchronized (dbHelper)
		{
			ArrayList<Module> moduleList = new ArrayList<Module>();
			SQLiteDatabase db = null;
			try
			{
				db = dbHelper.getReadableDatabase();
				String sql = SELECT;
				sql += showColumns != null ? showColumns : "*";
				sql += FROM + tableName;
				if (selection != null && selectionArgs != null)
				{
					sql += WHERE + selection + " = " + selectionArgs;
				}
				if (orderBy != null)
				{
					sql += ORDER_BY + orderBy;
				}
				Cursor cursor = db.rawQuery(sql, null);
				changeToList(cursor, moduleList, cls);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			finally
			{
				dbHelper.closeDatabase(db);
			}
			return moduleList;
		}
	}

	/**
	 * 查找数据表
	 *
	 * @param table
	 *            要操作的表
	 * @param selection
	 *            匹配条件,例如"id>?and name <>?",不需要可以设为null
	 * @param selectionArgs
	 *            与selection相对应,里面的字符串将替换selection里的"?",
	 *            构成完整的匹配条件,例如{"6","jack"}
	 * @param orderby 排序参数
	 * @param moduleClass
	 *            要转化成的模型类Class,例如要转成WebPage则传入WebPage.class
	 * @return 数据模型集合,集合是的对象类型为moduleClass
	 */
	public ArrayList<Module> select(final String table, final String selection, final String[] selectionArgs,
			final String orderby, final Class<?> moduleClass)
	{
		SQLiteDatabase database = null;
		Cursor cursor = null;
		ArrayList<Module> moduleList = new ArrayList<Module>();
		synchronized (dbHelper)
		{

			try
			{
				database = dbHelper.getReadableDatabase();
				// 查询数据
				cursor = database.query(table, null, selection, selectionArgs, null, null, orderby, null);
				// 将结果转换成为数据模型
				changeToList(cursor, moduleList, moduleClass);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			finally
			{
				dbHelper.closeDatabase(database);
			}
			return moduleList;
		}
	}

	private void changeToList(Cursor cursor, List<Module> modules, Class<?> moduleClass)
	{
		// 取出所有的列名
		int count = cursor.getCount();
		Module module;
		cursor.moveToFirst();
		synchronized (dbHelper)
		{
			try
			{
				// 遍历游标
				for (int i = 0; i < count; i++)
				{
					// 转化为moduleClass类的一个实例
					module = changeToModule(cursor, moduleClass);
					modules.add(module);
					cursor.moveToNext();
				}
			}
			catch (SecurityException e)
			{
				// Log.e(TAG, e + FusionCode.EMPTY_STRING);
			}
			catch (IllegalArgumentException e)
			{
				// Log.e(TAG, e + FusionCode.EMPTY_STRING);
			}
			catch (IllegalAccessException e)
			{
				// Log.e(TAG, e + FusionCode.EMPTY_STRING);
			}
			catch (InstantiationException e)
			{
				// Log.e(TAG, e + FusionCode.EMPTY_STRING);
			}
			catch (NoSuchFieldException e)
			{
				System.out.println("");
			}
			finally
			{
				cursor.close();
			}
		}
	}

	private Module changeToModule(Cursor cursor, Class<?> moduleClass) throws IllegalAccessException,
			InstantiationException, SecurityException, NoSuchFieldException
	{
		synchronized (dbHelper)
		{
			// 取出所有的列名
			String[] columnNames = cursor.getColumnNames();
			String filedValue;
			int columncount = columnNames.length;
			Field field;
			Module module = (Module) moduleClass.newInstance();
			// 遍历有列
			for (int j = 0; j < columncount; j++)
			{
				// 根据列名找到相对应 的字段
				field = moduleClass.getField(columnNames[j]);
				filedValue = cursor.getString(j);
				if (filedValue != null)
				{
					field.set(module, filedValue.trim());
				}
			}
			return module;
		}
	}

	/**
	 * 向数据库插入数据
	 *
	 * @param table
	 *            要操作的表
	 * @param module
	 *            数据模型,id设为自增,若没指定,则自动生成;若指定则插入指定的id,
	 *            但是在数据表已存在该id的情况下会导致插入失败,建议不指定id
	 * @return 插入行的行号,可以看作是id
	 */
	public long insert(final String table, final Module module)
	{
		synchronized (dbHelper)
		{
			ContentValues values = moduleToContentValues(module);
			return dbHelper.insert(table, null, values);
		}
	}

	/**
	 * 向数据库更新数据
	 *
	 * @param table
	 *            要操作的表
	 * @param module
	 * @return 更新行的行号,可以看作是id
	 */
	public long update(final String table, final Module module)
	{
		synchronized (dbHelper)
		{
			ContentValues values = moduleToContentValues(module);
			return dbHelper.update(table, values, DBHelper.ID + "=?", new String[]
			{ module.id });
		}
	}

	/**
	 * 删除一条数据记录
	 *
	 * @param table
	 *            要操作的表
	 * @param module
	 *            数据模型,该操作是根据id删除的,若id为null或不正确是不能成功删除的
	 * @return 数据表受影响的行数,0或1
	 */
	public int delete(final String table, final Module module)
	{
		synchronized (dbHelper)
		{
			return dbHelper.delete(table, "id=?", new String[]
			{ module.id });
		}
	}

	/**
	 * 删除数据
	 *
	 * @param table
	 *            要操作的表
	 * @param whereClause
	 *            匹配条件,例如"id>?and name <>?",符合条件的记录将被删除,
	 *            不需要可以设为null,这样整张表的内容都会被删除
	 * @param whereArgs
	 *            与selection相对应,里面的字符串将替换selection里的"?",
	 *            构成完整的匹配条件,例如{"6","jack"}
	 * @return 数据表受影响的行数
	 */
	public int delete(final String table, final String whereClause, final String[] whereArgs)
	{
		synchronized (dbHelper)
		{

			return dbHelper.delete(table, whereClause, whereArgs);

		}
	}

	/**
	 * 将Module类型转成ContentValues
	 *
	 * @param module
	 *            源Module
	 * @return ContentValues
	 * @author shenghua.lin
	 */
	private ContentValues moduleToContentValues(final Module module)
	{
		  ContentValues values = new ContentValues();
		  Field[] fields = module.getClass().getFields();
		  String fieldName;
		  String fieldValue;
		  int fieldValueForInt = -1;
		try
		{
			for (Field field : fields)
			{
				fieldName = field.getName();
				if (field.get(module) instanceof String)
				{
					fieldValue = (String) field.get(module);
					if (fieldValue != null)
					{
						values.put(fieldName, fieldValue.trim());
					}
					else
					{
						values.put(fieldName, "");
					}
				}
				else if (field.get(module) instanceof Integer)
				{
					fieldValueForInt = (Integer) field.get(module);
					if (fieldValueForInt != -1)
					{
						values.put(fieldName, fieldValueForInt);
					}
				}
			}
		}
		catch (IllegalArgumentException e)
		{
		}
		catch (IllegalAccessException e)
		{
		}
		return values;
	}
}

思路: 对Sqlite的CRUD操作,其实就是实体类与android ContentValues的相互转化,那么我们通过反射,是可以做到两种类间的相互转化的,也就可以实现ORM映射了.避免了引入第三方库的学习成本.

时间: 2024-10-08 18:00:47

android Sqlite操作之-- 自定义ORM关系实体映射类的相关文章

一:ORM关系对象映射(Object Relational Mapping,简称ORM)

狼来的日子里! 奋发博取 10)django-ORM(创建,字段类型,字段参数) 一:ORM关系对象映射(Object Relational Mapping,简称ORM) ORM分两种: DB first 先在数据库中创建数据库表等 Code first 先创建类,然后根据类创建数据表等.django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表. 二:Django ORM创建 1)创建类 创建的类必须继承models.Model,在数据库中自动创建表名为:app

abp 修改abp.zero的实体映射类,使生成的表和字段为大写状态

在我们项目中,由于涉及到报表配置管理,可以通过一段sql快捷的配置出一个报表页面.部分sql会与abp框架的一些系统表做关联查询,而abp的映射类没有单独设置表和字段的名称,默认用类名和属性名,区分大小写,造成写sql时需要对这些表加入双引号,不是很方便.本篇文章是修改abp.zero的实体映射类,分别为其表名和字段设定大写值. 由于我的项目还使用的是Abp.Zero.1.5.1版本,故下载了源码并对其所有实体类做了修改. 看一个截图: 我这里已经把相关的表及字段全部调整了,可直接下载调整以后的

EF Code First:实体映射,数据迁移,重构(1)

一.前言 经过EF的<第一篇>,我们已经把数据访问层基本搭建起来了,但并没有涉及实体关系.实体关系对于一个数据库系统来说至关重要,而且EF的各个实体之间的联系,实体之间的协作,联合查询等也都依赖于这些实体关系. 二.实体映射 实体与数据库的映射可以通过DataAnnotation与FluentAPI两种方式来进行映射: (一) DataAnnotation DataAnnotation 特性由.NET 3.5中引进,给.NET中的类提供了一种添加验证的方式.DataAnnotation由命名空

Android Sqlite的操作

1.写一个类继承SQLiteOpenHelper public class MyHelper extends SQLiteOpenHelper { public MyHelper(Context context) { super(context, Const.DB_DBNAME , null, Const.DB_VERSION); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteData

Android SQLite的ORM接口实现(一)---findAll和find的实现

最近在看Android的ORM数据库框架LitePal,就想到可以利用原生的SQLite来实现和LitePal类似的ORM接口实现. LitePal有一个接口是这样的: List<Status> statuses = DataSupport.findAll(Status.class); 指定什么类型,就能获取到该类型的数据集合. 这样是很方便,于是想着自己不看它们的实现,自己搞一个出来. 首先想到的就是利用反射和泛型. 利用反射有一个比较好的方式就是注解,读取注解就知道哪些属性是要被赋值的,但

android sqlite orm

要过年了,最近比较闲整理下以前的代码. 14年写的sqlite orm库,当时为了尽快熟悉android数据库操作,所以自己动手写了这个库.然后用这个库开发了几个项目发现用的还是比较顺手的,于是就写篇博客记录下吧. 我理解的orm的核心思想就是以对象为单位进行增删改查. app开发给字段命名是很麻烦的一件事,特别是当页面有很多控件的时候,要兼顾接口开发人员命名风格和页面快速辨认需求,如果orm再要求字段名还要考虑到数据表字段命名的问题就太麻烦了,于是我使用了反射来实现模型字段和数据表字段的对应.

【Android基础】Android SQLite存储自定义对象

Android SQLite存储自定义对象 在SQLite数据库中可存储的数据类型有NULL.INTEGER.REAL(浮点型).TEXT.BOOL,一共是五种数据类型.在Android开发中,我们存储数据的一般的作法是数据库的属性就是类的成员变量,比如: 要存储一个人的姓名和年龄,在类中的是将它们定义为两个成员变量 class Person{ private String name; private int age; } 数据库中是将它们存储为两个字段 - name TEXT - age IN

[Android] SQLite数据库之增删改查基础操作

    在编程中常常会遇到数据库的操作,而Android系统内置了SQLite,它是一款轻型数据库,遵守事务ACID的关系型数据库管理系统,它占用的资源非常低,可以支持Windows/Linux/Unix等主流操作系统,同一时候可以跟非常多程序语言如C#.PHP.Java等相结合.以下先回想SQL的基本语句,再讲述Android的基本操作. 一. adb shell回想SQL语句     首先,我感觉自己整个大学印象最深的几门课就包含<数据库>,所以想先回想SQL增删改查的基本语句.而在And

[Android新手区] SQLite 操作详解--SQL语法

该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法  :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解析大部分标准SQL语言.但它也省去了一些特性并且加入了一些自己的新特性.这篇文档就是试图描述那些SQLite支持/不支持的SQL语法的.查看关键字列表. 如下语法表格中,纯文本用蓝色粗体显示.非终极符号为斜体红色.作为语法一部分的运算符用黑色Roman字体表示. 这篇文档只是对SQLite实现的SQ