/* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.db.orm.dao; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.sql.Blob; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import com.ab.db.AbBasicDBDao; import com.ab.db.orm.AbTableHelper; import com.ab.db.orm.annotation.ActionType; import com.ab.db.orm.annotation.Column; import com.ab.db.orm.annotation.Id; import com.ab.db.orm.annotation.Relations; import com.ab.db.orm.annotation.RelationsType; import com.ab.db.orm.annotation.Table; import com.ab.util.AbLogUtil; import com.ab.util.AbStrUtil; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbDBDaoImpl.java * 描述:数据库表操作类接口实现类 * * @author 还如一梦中 * @version v1.0 * @param <T> the generic type * @date:2013-7-23 上午9:47:10 */ public class AbDBDaoImpl<T> extends AbBasicDBDao implements AbDBDao<T> { /** The db helper. */ private SQLiteOpenHelper dbHelper; /** 锁对象. */ private final ReentrantLock lock = new ReentrantLock(); /** The table name. */ private String tableName; /** The id column. */ private String idColumn; /** The clazz. */ private Class<T> clazz; /** The all fields. */ private List<Field> allFields; /** The Constant METHOD_INSERT. */ private static final int METHOD_INSERT = 0; /** The Constant METHOD_UPDATE. */ private static final int METHOD_UPDATE = 1; /** The Constant TYPE_NOT_INCREMENT. */ private static final int TYPE_NOT_INCREMENT = 0; /** The Constant TYPE_INCREMENT. */ private static final int TYPE_INCREMENT = 1; /** 这个Dao的数据库对象. */ private SQLiteDatabase db = null; /** * 用一个对象实体初始化这个数据库操作实现类. * * @param dbHelper 数据库操作实现类 * @param clazz 映射对象实体 */ public AbDBDaoImpl(SQLiteOpenHelper dbHelper, Class<T> clazz) { this.dbHelper = dbHelper; if (clazz == null) { this.clazz = ((Class<T>) ((java.lang.reflect.ParameterizedType) super .getClass().getGenericSuperclass()) .getActualTypeArguments()[0]); } else { this.clazz = clazz; } if (this.clazz.isAnnotationPresent(Table.class)) { Table table = (Table) this.clazz.getAnnotation(Table.class); this.tableName = table.name(); } // 加载所有字段 this.allFields = AbTableHelper.joinFields(this.clazz.getDeclaredFields(), this.clazz.getSuperclass().getDeclaredFields()); // 找到主键 for (Field field : this.allFields) { if (field.isAnnotationPresent(Id.class)) { Column column = (Column) field.getAnnotation(Column.class); this.idColumn = column.name(); break; } } AbLogUtil.d(AbDBDaoImpl.class, "clazz:" + this.clazz + " tableName:" + this.tableName + " idColumn:" + this.idColumn); } /** * 初始化这个数据库操作实现类. * * @param dbHelper 数据库操作实现类 */ public AbDBDaoImpl(SQLiteOpenHelper dbHelper) { this(dbHelper, null); } /** * 描述:TODO. * * @return the db helper * @see com.ab.db.orm.dao.AbDBDao#getDbHelper() */ @Override public SQLiteOpenHelper getDbHelper() { return dbHelper; } /** * 描述:查询一条. * * @param id the id * @return the t * @see com.ab.db.orm.dao.AbDBDao#queryOne(int) */ @Override public T queryOne(int id) { synchronized (lock) { String selection = this.idColumn + " = ?"; String[] selectionArgs = { Integer.toString(id) }; AbLogUtil.d(AbDBDaoImpl.class, "[queryOne]: select * from " + this.tableName + " where " + this.idColumn + " = '" + id + "'"); List<T> list = queryList(null, selection, selectionArgs, null, null, null, null); if ((list != null) && (list.size() > 0)) { return (T) list.get(0); } return null; } } /** * 描述:一种更灵活的方式查询,不支持对象关联,可以写完整的sql. * * @param sql 完整的sql如:select * from a ,b where a.id=b.id and a.id = ? * @param selectionArgs 绑定变量值 * @param clazz 返回的对象类型 * @return the list * @see com.ab.db.orm.dao.AbDBDao#rawQuery(java.lang.String, java.lang.String[]) */ @Override public List<T> rawQuery(String sql, String[] selectionArgs,Class<T> clazz) { List<T> list = new ArrayList<T>(); Cursor cursor = null; try { lock.lock(); checkDBOpened(); AbLogUtil.d(AbDBDaoImpl.class, "[rawQuery]: " + getLogSql(sql, selectionArgs)); cursor = db.rawQuery(sql, selectionArgs); getListFromCursor(clazz,list, cursor); } catch (Exception e) { AbLogUtil.e(AbDBDaoImpl.class, "[rawQuery] from DB Exception."); e.printStackTrace(); } finally { closeCursor(cursor); lock.unlock(); } return list; } /** * 描述:是否存在. * * @param sql the sql * @param selectionArgs the selection args * @return true, if is exist * @see com.ab.db.orm.dao.AbDBDao#isExist(java.lang.String, java.lang.String[]) */ @Override public boolean isExist(String sql, String[] selectionArgs) { Cursor cursor = null; try { lock.lock(); checkDBOpened(); AbLogUtil.d(AbDBDaoImpl.class, "[isExist]: " + getLogSql(sql, selectionArgs)); cursor = db.rawQuery(sql, selectionArgs); if (cursor.getCount() > 0) { return true; } } catch (Exception e) { AbLogUtil.e(AbDBDaoImpl.class, "[isExist] from DB Exception."); e.printStackTrace(); } finally { closeCursor(cursor); lock.unlock(); } return false; } /** * 描述:查询所有数据. * * @return the list * @see com.ab.db.orm.dao.AbDBDao#queryList() */ @Override public List<T> queryList() { return queryList(null, null, null, null, null, null, null); } /** * 描述:查询列表. * * @param columns the columns * @param selection the selection * @param selectionArgs the selection args * @param groupBy the group by * @param having the having * @param orderBy the order by * @param limit the limit * @return the list * @see com.ab.db.orm.dao.AbDBDao#queryList(java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ @Override public List<T> queryList(String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) { List<T> list = new ArrayList<T>(); Cursor cursor = null; try { lock.lock(); checkDBOpened(); AbLogUtil.d(AbDBDaoImpl.class, "[queryList] from "+this.tableName+" where "+selection+"("+selectionArgs+")"+" group by "+groupBy+" having "+having+" order by "+orderBy+" limit "+limit); cursor = db.query(this.tableName, columns, selection, selectionArgs, groupBy, having, orderBy, limit); getListFromCursor(this.clazz,list, cursor); closeCursor(cursor); //获取关联域的操作类型和关系类型 String foreignKey = null; String type = null; String action = null; //需要判断是否有关联表 for (Field relationsField : allFields) { if (!relationsField.isAnnotationPresent(Relations.class)) { continue; } Relations relations = (Relations) relationsField.getAnnotation(Relations.class); //获取外键列名 foreignKey = relations.foreignKey(); //关联类型 type = relations.type(); //操作类型 action = relations.action(); //设置可访问 relationsField.setAccessible(true); if(!(action.indexOf(ActionType.query)!=-1)){ return list; } //得到关联表的表名查询 for(T entity:list){ if(RelationsType.one2one.equals(type)){ //一对一关系 //获取这个实体的表名 String relationsTableName = ""; if (relationsField.getType().isAnnotationPresent(Table.class)) { Table table = (Table) relationsField.getType().getAnnotation(Table.class); relationsTableName = table.name(); } List<T> relationsList = new ArrayList<T>(); Field[] relationsEntityFields = relationsField.getType().getDeclaredFields(); for (Field relationsEntityField : relationsEntityFields) { Column relationsEntityColumn = (Column) relationsEntityField.getAnnotation(Column.class); //获取外键的值作为关联表的查询条件 if (relationsEntityColumn != null && relationsEntityColumn.name().equals(foreignKey)) { //主表的用于关联表的foreignKey值 String value = "-1"; for (Field entityField : allFields) { //设置可访问 entityField.setAccessible(true); Column entityForeignKeyColumn = (Column) entityField.getAnnotation(Column.class); if(entityForeignKeyColumn==null){ continue; } if (entityForeignKeyColumn.name().equals(foreignKey)) { value = String.valueOf(entityField.get(entity)); break; } } //查询数据设置给这个域 cursor = db.query(relationsTableName, null, foreignKey+" = ?",new String[]{value}, null, null, null, null); getListFromCursor(relationsField.getType(),relationsList, cursor); if(relationsList.size()>0){ //获取关联表的对象设置值 relationsField.set(entity, relationsList.get(0)); } break; } } }else if(RelationsType.one2many.equals(type) || RelationsType.many2many.equals(type)){ //一对多关系 //得到泛型里的class类型对象 Class listEntityClazz = null; Class<?> fieldClass = relationsField.getType(); if(fieldClass.isAssignableFrom(List.class)){ Type fc = relationsField.getGenericType(); if(fc == null) continue; if(fc instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) fc; listEntityClazz = (Class)pt.getActualTypeArguments()[0]; } } if(listEntityClazz==null){ AbLogUtil.e(AbDBDaoImpl.class, "对象模型需要设置List的泛型"); return null; } //得到表名 String relationsTableName = ""; if (listEntityClazz.isAnnotationPresent(Table.class)) { Table table = (Table) listEntityClazz.getAnnotation(Table.class); relationsTableName = table.name(); } List<T> relationsList = new ArrayList<T>(); Field[] relationsEntityFields = listEntityClazz.getDeclaredFields(); for (Field relationsEntityField : relationsEntityFields) { Column relationsEntityColumn = (Column) relationsEntityField.getAnnotation(Column.class); //获取外键的值作为关联表的查询条件 if (relationsEntityColumn != null && relationsEntityColumn.name().equals(foreignKey)) { //主表的用于关联表的foreignKey值 String value = "-1"; for (Field entityField : allFields) { //设置可访问 entityField.setAccessible(true); Column entityForeignKeyColumn = (Column) entityField.getAnnotation(Column.class); if (entityForeignKeyColumn.name().equals(foreignKey)) { value = String.valueOf(entityField.get(entity)); break; } } //查询数据设置给这个域 cursor = db.query(relationsTableName, null, foreignKey+" = ?",new String[]{value}, null, null, null, null); getListFromCursor(listEntityClazz,relationsList, cursor); if(relationsList.size()>0){ //获取关联表的对象设置值 relationsField.set(entity, relationsList); } break; } } } } } } catch (Exception e) { AbLogUtil.e(AbDBDaoImpl.class, "[queryList] from DB Exception"); e.printStackTrace(); } finally { closeCursor(cursor); lock.unlock(); } return list; } /** * 描述:简单一些的查询. * * @param selection the selection * @param selectionArgs the selection args * @return the list * @see com.ab.db.orm.dao.AbDBDao#queryList(java.lang.String, java.lang.String[]) * @author: amsoft.cn */ @Override public List<T> queryList(String selection, String[] selectionArgs) { return queryList(null, selection,selectionArgs, null, null,null, null); } /** * 从游标中获得映射对象列表. * * @param clazz the clazz * @param list 返回的映射对象列表 * @param cursor 当前游标 * @return the list from cursor * @throws IllegalAccessException the illegal access exception * @throws InstantiationException the instantiation exception */ private void getListFromCursor(Class<?> clazz,List<T> list, Cursor cursor) throws IllegalAccessException, InstantiationException { while (cursor.moveToNext()) { Object entity = clazz.newInstance(); // 加载所有字段 List<Field> allFields = AbTableHelper.joinFields(entity.getClass().getDeclaredFields(), entity.getClass().getSuperclass().getDeclaredFields()); for (Field field : allFields) { Column column = null; if (field.isAnnotationPresent(Column.class)) { column = (Column) field.getAnnotation(Column.class); field.setAccessible(true); Class<?> fieldType = field.getType(); int c = cursor.getColumnIndex(column.name()); if (c < 0) { continue; // 如果不存则循环下个属性值 } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) { field.set(entity, cursor.getInt(c)); } else if (String.class == fieldType) { field.set(entity, cursor.getString(c)); } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) { field.set(entity, Long.valueOf(cursor.getLong(c))); } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) { field.set(entity, Float.valueOf(cursor.getFloat(c))); } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) { field.set(entity, Short.valueOf(cursor.getShort(c))); } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) { field.set(entity, Double.valueOf(cursor.getDouble(c))); } else if (Date.class == fieldType) {// 处理java.util.Date类型,update2012-06-10 Date date = new Date(); date.setTime(cursor.getLong(c)); field.set(entity, date); } else if (Blob.class == fieldType) { field.set(entity, cursor.getBlob(c)); } else if (Character.TYPE == fieldType) { String fieldValue = cursor.getString(c); if ((fieldValue != null) && (fieldValue.length() > 0)) { field.set(entity, Character.valueOf(fieldValue.charAt(0))); } }else if ((Boolean.TYPE == fieldType) || (Boolean.class == fieldType)) { String temp = cursor.getString(c); if ("true".equals(temp) || "1".equals(temp)){ field.set(entity, true); }else{ field.set(entity, false); } } } } list.add((T) entity); } } /** * 描述:插入实体. * * @param entity the entity * @return the long * @see com.ab.db.orm.dao.AbDBDao#insert(java.lang.Object) */ @Override public long insert(T entity) { return insert(entity, true); } /** * 描述:插入实体. * @param entity the entity * @param flag the flag * @return the long * @see com.ab.db.orm.dao.AbDBDao#insert(java.lang.Object, boolean) */ @Override public long insert(T entity, boolean flag) { String sql = null; long rowId = -1; try { lock.lock(); checkDBOpened(); ContentValues cv = new ContentValues(); if (flag) { // id自增 sql = setContentValues(entity, cv, TYPE_INCREMENT,METHOD_INSERT); } else { // id需指定 sql = setContentValues(entity, cv, TYPE_NOT_INCREMENT,METHOD_INSERT); } AbLogUtil.d(AbDBDaoImpl.class, "[insert]: insert into " + this.tableName + " " + sql); rowId = db.insert(this.tableName, null, cv); //获取关联域的操作类型和关系类型 String foreignKey = null; String type = null; String action = null; //需要判断是否有关联表 for (Field relationsField : allFields) { if (!relationsField.isAnnotationPresent(Relations.class)) { continue; } Relations relations = (Relations) relationsField.getAnnotation(Relations.class); //获取外键列名 foreignKey = relations.foreignKey(); //关联类型 type = relations.type(); //操作类型 action = relations.action(); //设置可访问 relationsField.setAccessible(true); if(!(action.indexOf(ActionType.insert)!=-1)){ return rowId; } if(RelationsType.one2one.equals(type)){ //一对一关系 //获取关联表的对象 T relationsEntity = (T)relationsField.get(entity); if(relationsEntity != null){ ContentValues relationsCv = new ContentValues(); if (flag) { // id自增 sql = setContentValues(relationsEntity, relationsCv, TYPE_INCREMENT,METHOD_INSERT); } else { // id需指定 sql = setContentValues(relationsEntity, relationsCv, TYPE_NOT_INCREMENT,METHOD_INSERT); } String relationsTableName = ""; if (relationsEntity.getClass().isAnnotationPresent(Table.class)) { Table table = (Table) relationsEntity.getClass().getAnnotation(Table.class); relationsTableName = table.name(); } AbLogUtil.d(AbDBDaoImpl.class, "[insert]: insert into " + relationsTableName + " " + sql); db.insert(relationsTableName, null, relationsCv); } }else if(RelationsType.one2many.equals(type) || RelationsType.many2many.equals(type)){ //一对多关系 //获取关联表的对象 List<T> list = (List<T>)relationsField.get(entity); if(list!=null && list.size()>0){ for(T relationsEntity:list){ ContentValues relationsCv = new ContentValues(); if (flag) { // id自增 sql = setContentValues(relationsEntity, relationsCv, TYPE_INCREMENT,METHOD_INSERT); } else { // id需指定 sql = setContentValues(relationsEntity, relationsCv, TYPE_NOT_INCREMENT,METHOD_INSERT); } String relationsTableName = ""; if (relationsEntity.getClass().isAnnotationPresent(Table.class)) { Table table = (Table) relationsEntity.getClass().getAnnotation(Table.class); relationsTableName = table.name(); } AbLogUtil.d(AbDBDaoImpl.class, "[insert]: insert into " + relationsTableName + " " + sql); db.insert(relationsTableName, null, relationsCv); } } } } } catch (Exception e) { AbLogUtil.d(AbDBDaoImpl.class, "[insert] into DB Exception."); e.printStackTrace(); }finally { lock.unlock(); } return rowId; } /** * 描述:插入列表. * * @param entityList the entity list * @return the long[] 插入成功的数据ID * @see com.ab.db.orm.dao.AbDBDao#insertList(java.util.List) */ @Override public long[] insertList(List<T> entityList) { return insertList(entityList, true); } /** * 描述:插入列表. * * @param entityList the entity list * @param flag the flag * @return the long[] 插入成功的数据ID * @see com.ab.db.orm.dao.AbDBDao#insertList(java.util.List, boolean) */ @Override public long[] insertList(List<T> entityList,boolean flag) { String sql = null; long[] rowIds = new long[entityList.size()]; for(int i=0;i<rowIds.length;i++){ rowIds[i] = -1; } try { lock.lock(); checkDBOpened(); for(int i=0;i<entityList.size();i++){ T entity = entityList.get(i); ContentValues cv = new ContentValues(); if (flag) { // id自增 sql = setContentValues(entity, cv, TYPE_INCREMENT,METHOD_INSERT); } else { // id需指定 sql = setContentValues(entity, cv, TYPE_NOT_INCREMENT,METHOD_INSERT); } AbLogUtil.d(AbDBDaoImpl.class, "[insertList]: insert into " + this.tableName + " " + sql); rowIds[i] = db.insert(this.tableName, null, cv); //获取关联域的操作类型和关系类型 String foreignKey = null; String type = null; String action = null; Field field = null; //需要判断是否有关联表 for (Field relationsField : allFields) { if (!relationsField.isAnnotationPresent(Relations.class)) { continue; } Relations relations = (Relations) relationsField.getAnnotation(Relations.class); //获取外键列名 foreignKey = relations.foreignKey(); //关联类型 type = relations.type(); //操作类型 action = relations.action(); //设置可访问 relationsField.setAccessible(true); field = relationsField; } if(field == null){ continue; } if(!(action.indexOf(ActionType.insert)!=-1)){ continue; } if(RelationsType.one2one.equals(type)){ //一对一关系 //获取关联表的对象 T relationsEntity = (T)field.get(entity); if(relationsEntity != null){ ContentValues relationsCv = new ContentValues(); if (flag) { // id自增 sql = setContentValues(relationsEntity, relationsCv, TYPE_INCREMENT,METHOD_INSERT); } else { // id需指定 sql = setContentValues(relationsEntity, relationsCv, TYPE_NOT_INCREMENT,METHOD_INSERT); } String relationsTableName = ""; if (relationsEntity.getClass().isAnnotationPresent(Table.class)) { Table table = (Table) relationsEntity.getClass().getAnnotation(Table.class); relationsTableName = table.name(); } AbLogUtil.d(AbDBDaoImpl.class, "[insertList]: insert into " + relationsTableName + " " + sql); db.insert(relationsTableName, null, relationsCv); } }else if(RelationsType.one2many.equals(type) || RelationsType.many2many.equals(type)){ //一对多关系 //获取关联表的对象 List<T> list = (List<T>)field.get(entity); if(list!=null && list.size()>0){ for(T relationsEntity:list){ ContentValues relationsCv = new ContentValues(); if (flag) { // id自增 sql = setContentValues(relationsEntity, relationsCv, TYPE_INCREMENT,METHOD_INSERT); } else { // id需指定 sql = setContentValues(relationsEntity, relationsCv, TYPE_NOT_INCREMENT,METHOD_INSERT); } String relationsTableName = ""; if (relationsEntity.getClass().isAnnotationPresent(Table.class)) { Table table = (Table) relationsEntity.getClass().getAnnotation(Table.class); relationsTableName = table.name(); } AbLogUtil.d(AbDBDaoImpl.class, "[insertList]: insert into " + relationsTableName + " " + sql); db.insert(relationsTableName, null, relationsCv); } } } } } catch (Exception e) { AbLogUtil.d(AbDBDaoImpl.class, "[insertList] into DB Exception."); e.printStackTrace(); } finally { lock.unlock(); } return rowIds; } /** * 描述:按id删除. * * @param id the id * @return the int * @see com.ab.db.orm.dao.AbDBDao#delete(int) */ @Override public int delete(int id) { int rows = 0; try { lock.lock(); checkDBOpened(); String where = this.idColumn + " = ?"; String[] whereValue = { Integer.toString(id) }; AbLogUtil.d(AbDBDaoImpl.class, "[delete]: delelte from " + this.tableName + " where " + where.replace("?", String.valueOf(id))); rows = db.delete(this.tableName, where, whereValue); } catch (Exception e) { AbLogUtil.d(AbDBDaoImpl.class, "[delete] DB Exception."); e.printStackTrace(); }finally{ lock.unlock(); } return rows; } /** * 描述:按id删除. * * @param ids the ids * @return the int * @see com.ab.db.orm.dao.AbDBDao#delete(java.lang.Integer[]) */ @Override public int delete(Integer... ids) { int rows = 0; if (ids.length > 0) { for (int i = 0; i < ids.length; i++) { rows += delete(ids[i]); } } return rows; } /** * 描述:按条件删除数据. * * @param whereClause the where clause * @param whereArgs the where args * @return the int * @see com.ab.db.orm.dao.AbDBDao#delete(java.lang.String, java.lang.String[]) */ @Override public int delete(String whereClause, String[] whereArgs) { int rows = 0; try { lock.lock(); checkDBOpened(); String mLogSql = getLogSql(whereClause,whereArgs); if(!AbStrUtil.isEmpty(mLogSql)){ mLogSql +=" where "; } AbLogUtil.d(AbDBDaoImpl.class, "[delete]: delete from " + this.tableName + mLogSql); rows = db.delete(this.tableName, whereClause, whereArgs); } catch (Exception e) { AbLogUtil.d(AbDBDaoImpl.class, "[delete] DB Exception."); e.printStackTrace(); }finally{ lock.unlock(); } return rows; } /** * 描述:清空数据. * * @return the int 影响的行 * @see com.ab.db.orm.dao.AbDBDao#deleteAll() */ @Override public int deleteAll() { int rows = 0; try { lock.lock(); checkDBOpened(); AbLogUtil.d(AbDBDaoImpl.class, "[delete]: delete from " + this.tableName ); rows = db.delete(this.tableName,null,null); } catch (Exception e) { AbLogUtil.d(AbDBDaoImpl.class, "[delete] DB Exception."); e.printStackTrace(); }finally{ lock.unlock(); } return rows; } /** * 描述:更新实体. * @param entity the entity * @return the int 影响的行 * @see com.ab.db.orm.dao.AbDBDao#update(java.lang.Object) */ @Override public int update(T entity) { int rows = 0; try { lock.lock(); checkDBOpened(); ContentValues cv = new ContentValues(); //注意返回的sql中包含主键列 String sql = setContentValues(entity, cv, TYPE_NOT_INCREMENT,METHOD_UPDATE); String where = this.idColumn + " = ?"; int id = Integer.parseInt(cv.get(this.idColumn).toString()); //set sql中不能包含主键列 cv.remove(this.idColumn); AbLogUtil.d(AbDBDaoImpl.class, "[update]: update " + this.tableName + " set " + sql + " where " + where.replace("?", String.valueOf(id))); String[] whereValue = { Integer.toString(id) }; rows = db.update(this.tableName, cv, where, whereValue); } catch (Exception e) { AbLogUtil.d(AbDBDaoImpl.class, "[update] DB Exception."); e.printStackTrace(); } finally { lock.unlock(); } return rows; } /** * 描述:更新列表. * * @param entityList the entity list * @return the int 影响的行 * @see com.ab.db.orm.dao.AbDBDao#updateList(java.util.List) */ @Override public int updateList(List<T> entityList) { String sql = null; int rows = 0; try { lock.lock(); checkDBOpened(); for(T entity:entityList){ ContentValues cv = new ContentValues(); sql = setContentValues(entity, cv, TYPE_NOT_INCREMENT, METHOD_UPDATE); String where = this.idColumn + " = ?"; int id = Integer.parseInt(cv.get(this.idColumn).toString()); cv.remove(this.idColumn); AbLogUtil.d(AbDBDaoImpl.class, "[update]: update " + this.tableName + " set " + sql + " where " + where.replace("?", String.valueOf(id))); String[] whereValue = { Integer.toString(id) }; rows += db.update(this.tableName, cv, where, whereValue); } } catch (Exception e) { AbLogUtil.d(AbDBDaoImpl.class, "[update] DB Exception."); e.printStackTrace(); } finally { lock.unlock(); } return rows; } /** * 设置这个ContentValues. * * @param entity 映射实体 * @param cv the cv * @param type id类的类型,是否自增 * @param method 预执行的操作 * @return sql的字符串 * @throws IllegalAccessException the illegal access exception */ private String setContentValues(T entity, ContentValues cv, int type, int method) throws IllegalAccessException { StringBuffer strField = new StringBuffer("("); StringBuffer strValue = new StringBuffer(" values("); StringBuffer strUpdate = new StringBuffer(" "); // 加载所有字段 List<Field> allFields = AbTableHelper.joinFields(entity.getClass().getDeclaredFields(), entity.getClass().getSuperclass().getDeclaredFields()); for (Field field : allFields) { if (!field.isAnnotationPresent(Column.class)) { continue; } Column column = (Column) field.getAnnotation(Column.class); field.setAccessible(true); Object fieldValue = field.get(entity); if (fieldValue == null) continue; if ((type == TYPE_INCREMENT) && (field.isAnnotationPresent(Id.class))) { continue; } // 处理java.util.Date类型,update if (Date.class == field.getType()) { // 2012-06-10 cv.put(column.name(), ((Date) fieldValue).getTime()); continue; } String value = String.valueOf(fieldValue); cv.put(column.name(), value); if (method == METHOD_INSERT) { strField.append(column.name()).append(","); strValue.append("'").append(value).append("',"); } else { strUpdate.append(column.name()).append("=").append("'").append( value).append("',"); } } if (method == METHOD_INSERT) { strField.deleteCharAt(strField.length() - 1).append(")"); strValue.deleteCharAt(strValue.length() - 1).append(")"); return strField.toString() + strValue.toString(); } else { return strUpdate.deleteCharAt(strUpdate.length() - 1).append(" ").toString(); } } /** * 描述:查询为map列表. * * @param sql the sql * @param selectionArgs the selection args * @return the list * @see com.ab.db.orm.dao.AbDBDao#queryMapList(java.lang.String, java.lang.String[]) */ @Override public List<Map<String, String>> queryMapList(String sql,String[] selectionArgs) { Cursor cursor = null; List<Map<String, String>> retList = new ArrayList<Map<String, String>>(); try { lock.lock(); checkDBOpened(); AbLogUtil.d(AbDBDaoImpl.class, "[queryMapList]: " + getLogSql(sql, selectionArgs)); cursor = db.rawQuery(sql, selectionArgs); while (cursor.moveToNext()) { Map<String, String> map = new HashMap<String, String>(); for (String columnName : cursor.getColumnNames()) { int c = cursor.getColumnIndex(columnName); if (c < 0) { continue; // 如果不存在循环下个属性值 } else { map.put(columnName.toLowerCase(), cursor.getString(c)); } } retList.add(map); } } catch (Exception e) { AbLogUtil.e(AbDBDaoImpl.class, "[queryMapList] from DB exception"); e.printStackTrace(); } finally { closeCursor(cursor); lock.unlock(); } return retList; } /** * 描述:查询数量. * @param sql the sql * @param selectionArgs the selection args * @return the int * @see com.ab.db.orm.dao.AbDBDao#queryCount(java.lang.String, java.lang.String[]) */ @Override public int queryCount(String sql, String[] selectionArgs) { Cursor cursor = null; int count = 0; try{ lock.lock(); checkDBOpened(); AbLogUtil.d(AbDBDaoImpl.class, "[queryCount]: " + getLogSql(sql, selectionArgs)); cursor = db.query(this.tableName, null, sql, selectionArgs, null, null,null); if(cursor != null){ count = cursor.getCount(); } }catch (Exception e){ AbLogUtil.e(AbDBDaoImpl.class, "[queryCount] from DB exception"); e.printStackTrace(); }finally{ closeCursor(cursor); lock.unlock(); } return count; } /** * 描述:执行特定的sql. * * @param sql the sql * @param selectionArgs the selection args * @see com.ab.db.orm.dao.AbDBDao#execSql(java.lang.String, java.lang.Object[]) */ @Override public void execSql(String sql, Object[] selectionArgs) { try { lock.lock(); checkDBOpened(); AbLogUtil.d(AbDBDaoImpl.class, "[execSql]: " + getLogSql(sql, selectionArgs)); if (selectionArgs == null) { db.execSQL(sql); } else { db.execSQL(sql, selectionArgs); } } catch (Exception e) { AbLogUtil.e(AbDBDaoImpl.class, "[execSql] DB exception."); e.printStackTrace(); } finally { lock.unlock(); } } /** * 描述:获取写数据库,数据操作前必须调用. * * @param transaction 是否开启事务 */ public void startWritableDatabase(boolean transaction){ try { lock.lock(); if(db == null || !db.isOpen()){ db = this.dbHelper.getWritableDatabase(); } if(db!=null && transaction){ db.beginTransaction(); } } catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } } /** * 描述:获取读数据库,数据操作前必须调用. */ public void startReadableDatabase(){ try { lock.lock(); if(db == null || !db.isOpen()){ db = this.dbHelper.getReadableDatabase(); } }catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } } /** * 描述:关闭数据库,数据操作后必须调用. */ public void closeDatabase(){ try { lock.lock(); if(db!=null){ if(db.inTransaction()){ db.setTransactionSuccessful(); db.endTransaction(); } if(db.isOpen()){ db.close(); } } }catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } } /** * 描述:关闭数据库 ,数据操作后必须调用. * 当发生异常时,事务可以回滚。 */ public void closeDatabaseAndRollback(){ try { lock.lock(); if(db!=null){ if(db.inTransaction()){ db.endTransaction(); } if(db.isOpen()){ db.close(); } } }catch (Exception e) { e.printStackTrace(); }finally{ lock.unlock(); } } /** * 打印当前sql语句. * * @param sql sql语句,带? * @param args 绑定变量 * @return 完整的sql */ private String getLogSql(String sql, Object[] args) { if (args == null || args.length == 0) { return sql; } for (int i = 0; i < args.length; i++) { sql = sql.replaceFirst("\\?", "'" + String.valueOf(args[i]) + "'"); } return sql; } /** * * 描述:检查DB是否已经打开. */ private void checkDBOpened(){ if(db == null){ throw new RuntimeException("先调用 startReadableDatabase()或者startWritableDatabase(boolean transaction)初始化数据库。"); } } }