ITEEDU

UtilDB用于Android的sqlite数据库

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.gzi.helper.Utils;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
/**
 * 要维护的方法:
 * getValueByField(Cursor cur, Field field)
 * 根据field的类型从Cursor中取数据生成对应对象
 * 当有新类型需求时要在分支中加入新的处理分支
 * putValueToContentValues(String cn, Object value,	Field f, ContentValues values) 
 * 将对象转换成ContentValues接收的类型,也要处理
 */
public class UtilDB extends BeanUtils{
	/**
	 * 根据Cursor生成对应的Bean并加到指定列表中
	 * 
	 * @param cur Cursor
	 * 
	 * @param bc 对应Bean的class
	 * 
	 * @param bl 一个存在的与存储生成bean类型对象的列表
	 */
	public static <T> void addBeanToList(Cursor cur, Class<T> bc,
			ArrayList<T> bl) throws BeanException {
		if (bl == null)
			return;// 列表不存在则返回
		if (cur != null && cur.getCount() > 0) {
			T bean = null;
			Object value = null;
			Field[] fs = bc.getDeclaredFields();
			ColumnHolder ch = null;
			// 生成Bean的列表
			while (cur.moveToNext()) {
				bean = newBeanByClass(bc);
				// 给bean实例赋值
				for (Field f : fs) {
					ch = new ColumnHolder(f);
					// cn = ch.columnName;
					if (!ch.isColumn)
						continue;// 非数据库中的列忽略
					value = getValueByField(cur, f,ch);
					setFieldValue(f, value, bean);
				}
				// 加入到列表中
				bl.add(bean);
			}
		}
	}
	/**
	 * 根据Cursor生成对应的Bean的列表
	 * 
	 * @param cur Cursor
	 * 
	 * @param bc 对应Bean的class
	 * 
	 * @return 生成的Bean的列表,如果cur没记录返回空list
	 */
	public static <T> ArrayList<T> getBeans(Cursor cur, Class<T> bc)
			throws BeanException {
		ArrayList<T> bl = new ArrayList<T>();
		if (cur != null && cur.getCount() > 0) {
			addBeanToList(cur, bc, bl);
		}
		return bl;
	}
	/**
	 * 根据field的类型从Cursor中生成对应的对象
	 * 
	 * @param cur 游标对象
	 * 
	 * @param field 属性域
	 * 
	 * @return Object 可能为null
	 */
	private static Object getValueByField(Cursor cur, Field field,ColumnHolder ch)
			throws BeanException {
		String columnName = ch.columnName;
		int ci = cur.getColumnIndex(columnName);
		if (ci == -1)
			return null;// 如果不存在此列则返回null
		Class fieldClass = field.getType();
		// 根据属性类型从Cursor中获取值
		if (fieldClass == String.class)
			return cur.getString(ci);
		else if (fieldClass == int.class || fieldClass == Integer.class)
			return cur.getInt(ci);
		else if (fieldClass == Date.class) {
			try {
				return Utils.parseChinaDate(cur.getString(ci),
						"yyyy-MM-dd HH:mm:ss");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				throw new BeanException("Date类型转换错误", e);
			}
		}
		// else if (fieldClass == ImageView.class) {
		// 处理图片
		// return cur.getBlob(ci);
		// }
		else if (fieldClass == Long.class)
			return cur.getLong(ci);
		else if (fieldClass == Double.class)
			return cur.getDouble(ci);
		else if (fieldClass == Float.class)
			return cur.getFloat(ci);
		else if (fieldClass == Short.class)
			return cur.getShort(ci);
		return null;
	}
	private static class ColumnHolder {
		public String columnName;
		public boolean canNull = true;
		public boolean isKey = false;
		public boolean isColumn = true;
		public ColumnHolder(Field field) {
			// 根据注释获取属性对应的列名
			Column column = field.getAnnotation(Column.class);
			if (column != null) {
				if (!column.value().equals(Column.defaultColumnName))
					columnName = column.value();
				else
					columnName = field.getName().toLowerCase();
				
				canNull = column.canNull();
				isKey = column.isKey();
				isColumn = column.isColumn();
				
			} else {
				// 没有注释则根据属性名小写化后的名字作列名
				columnName = field.getName().toLowerCase();
				
			}
		}
	}
	private static class TableHolder {
		public String tableName;
		public TableHolder(Class bc) {
			Table a = (Table) bc.getAnnotation(Table.class);
			if (a != null)
				tableName = a.value();
			else
				tableName = bc.getName().toLowerCase();
		}
	}
	private static void putValueToContentValues(String cn, Object value,
			Field f, ContentValues values) throws BeanException {
		Class fieldClass = f.getType();
		// 根据属性类型为values赋值
		if (fieldClass == String.class)
			values.put(cn, (String) value);
		else if (fieldClass == int.class || fieldClass == Integer.class)
			values.put(cn, (Integer) value);
		else if (fieldClass == Date.class) {
			try {
				values.put(cn, Utils.formatGMTDate((Date) value,
						"yyyy-MM-dd HH:mm:ss"));
			} catch (Exception e) {
				// TODO Auto-generated catch block
				throw new BeanException("Date类型转换错误", e);
			}
		}
		// else if (fieldClass == ImageView.class) {
		// 处理图片
		// values.put(cn, (byte[])value);
		// }
		else if (fieldClass == Long.class)
			values.put(cn, (Long) value);
		else if (fieldClass == Double.class)
			values.put(cn, (Double) value);
		else if (fieldClass == Float.class)
			values.put(cn, (Float) value);
		else if (fieldClass == Short.class)
			values.put(cn, (Short) value);
	}
/**
 * 插入bean列表到数据库中
 * @param beans
 * @param db
 * @return
 * @throws BeanException
 */
	public static <T> long InsertBeanList(List<T> beans, SQLiteDatabase db)
			throws BeanException {
		db.beginTransaction();
		try {
			for (T bean : beans) {
				InsertBean(bean, db);
			}
			db.setTransactionSuccessful();
		} catch (BeanException e) {
			// TODO Auto-generated catch block
			db.endTransaction();
			throw e;
		} finally {
			db.endTransaction();
		}
		return beans.size();
	}
	/**
	 * 将bean插入到数据库中,bean中有canNull=false注释的属性一定不能为空,否则抛出异常
	 * 
	 * @param bean
	 * 
	 * @param db
	 * 
	 * @return  插入行的id
	 */
	public static <T> long InsertBean(T bean, SQLiteDatabase db)
			throws BeanException {
		Field[] fs = bean.getClass().getDeclaredFields();
		ContentValues values = new ContentValues();
		String cn = null;
		Object value = null;
		ColumnHolder ch = null;
		for (Field f : fs) {
			ch = new ColumnHolder(f);
			cn = ch.columnName;
			if (!ch.isColumn)
				continue;// 非数据库中的列忽略
			value = getFieldValue(bean, f);
			// 当不能为空的属性为空时,抛出异常
			if (value == null && !ch.canNull)
				throw new BeanException("InsertBean属性不能为空:canNull=false注释,属性"
						+ f.getName(), null);
			if (value == null)
				continue;
			putValueToContentValues(cn, value, f, values);
		}
		long id = -1;
		try {
			id = db.insertOrThrow(new TableHolder(bean.getClass()).tableName,
					null, values);
		} catch (SQLException e) {
			throw new BeanException("InsertBean插入记录不成功:" + e.getMessage(), e);
		}
		return id;
	}
	/**
	 * 删除数据库中的记录,条件由传入的bean含有key注释的属性生成, 支持多列组成的主键, bean的其它属性不做处理,只处理含有key注释的属性
	 * 
	 * @param bean 含有主键的bean
	 * 
	 * @param db 可写数据库
	 * 
	 * @return 删除记录数,这里一定为1,因为是主键定的条件
	 */
	public static <T> int deleteBeanByKey(T bean, SQLiteDatabase db)
			throws BeanException {
		Field[] fs = bean.getClass().getDeclaredFields();
		String cn = null;
		Object value = null;
		ColumnHolder ch = null;
		String where = null;
		for (Field f : fs) {
			ch = new ColumnHolder(f);
			if (!ch.isKey)
				continue;// 不是key主键不做处理
			cn = ch.columnName;
			value = getFieldValue(bean, f);
			// 当值为空,抛出异常,因為到這一定是主鍵類型,不能為空
			if (value == null)
				throw new BeanException("deleteBeanByKey属性不能为空:isKey=true注释属性"
						+ f.getName(), null);
			where = getWhere(where, cn, value);
		}
		if (where == null)
			throw new BeanException("deleteBeanByKey删除记录:条件设置不正确where为空", null);
		int count = -1;
		count = db.delete(new TableHolder(bean.getClass()).tableName, where,
				null);
		return count;
	}
	/**
	 * 对where追加项,格式为ColumnName=Value
	 * 
	 * @param where 要追加的字符串
	 * 
	 * @param cn 列名
	 * 
	 * @param value 要追加的值
	 */
	private static String getWhere(String where, String cn, Object value) {
		if (where == null)
			where = cn + "='" + String.valueOf(value) + "'";
		else
			where += " and " + cn + "='" + String.valueOf(value) + "'";
		return where;
	}
	/**
	 * 更新数据库中的记录,条件由传入的bean含有key注释的属性生成, 支持多列组成的主键
	 * 
	 * 除了key注释的属性的其它属性,只要不为null就会被更新。
	 * 
	 * key注释的属性不可更新,因为那样就相当于新建了一条记录了。
	 * 
	 * @param bean 含有主键的bean
	 * 
	 * @param db 可写数据库
	 * 
	 * @return 更新记录数,这里一定为1,因为是主键定的条件
	 */
	public static <T> int updateBeanByKey(T bean, SQLiteDatabase db)
			throws BeanException {
		Field[] fs = bean.getClass().getDeclaredFields();
		ContentValues values = new ContentValues();
		String cn = null;
		Object value = null;
		ColumnHolder ch = null;
		String where = null;
		for (Field f : fs) {
			ch = new ColumnHolder(f);
			cn = ch.columnName;
			if (!ch.isColumn)
				continue;// 非数据库中的列忽略
			value = getFieldValue(bean, f);
			if (ch.isKey) {
				// 当值为空,抛出异常,因為到這一定是主鍵類型,不能為空
				if (value == null)
					throw new BeanException(
							"deleteBeanByKey属性不能为空:isKey=true注释属性"
									+ f.getName(), null);
				where = getWhere(where, cn, value);
			} else {
				if (value == null)
					continue;
				putValueToContentValues(cn, value, f, values);
			}
		}
		if (where == null)
			throw new BeanException("updateBeanByKey更新记录:条件设置不正确where为空", null);
		if (values.size() <= 0)
			throw new BeanException("updateBeanByKey更新记录:没有要更新的值", null);
		int count = -1;
		count = db.update(new TableHolder(bean.getClass()).tableName, values,
				where, null);
		return count;
	}
	/**
	 * 更新数据库中的记录,条件由传入的bean含有key注释的属性生成, 支持多列组成的主键
	 * 
	 * 除了key注释的属性的其它属性,只要不为null就会被更新。
	 * 
	 * key注释的属性不可更新,因为那样就相当于新建了一条记录了。
	 * 
	 * @param bean 含有主键的bean列表
	 * 
	 * @param db 可写数据库
	 * 
	 * @return 更新记录数,这里一定为1,因为是主键定的条件
	 */
	public static <T> int updateBeanListByKey(ArrayList<T> beans,
			SQLiteDatabase db) throws BeanException {
		db.beginTransaction();
		try {
			for (T bean : beans) {
				updateBeanByKey(bean, db);
			}
			db.setTransactionSuccessful();
		} catch (BeanException e) {
			// TODO Auto-generated catch block
			db.endTransaction();
			throw e;
		} finally {
			db.endTransaction();
		}
		return beans.size();
	}
	/**
	 * 删除数据库中的记录,条件由传入的bean含有key注释的属性生成, 支持多列组成的主键, bean的其它属性不做处理,只处理含有key注释的属性
	 * 
	 * @param beans 含有主键的bean的列表
	 * 
	 * @param db 可写数据库
	 * 
	 * @return 删除记录数
	 */
	public static <T> int deleteBeanListByKey(ArrayList<T> beans,
			SQLiteDatabase db) throws BeanException {
		db.beginTransaction();
		try {
			for (T bean : beans) {
				deleteBeanByKey(bean, db);
			}
			db.setTransactionSuccessful();
		} catch (BeanException e) {
			// TODO Auto-generated catch block
			db.endTransaction();
			throw e;
		} finally {
			db.endTransaction();
		}
		return beans.size();
	}
	
}