package com.litesuits.orm.db.assit; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import android.os.Build; import android.util.Log; import com.litesuits.orm.db.TableManager; import com.litesuits.orm.db.assit.Querier.CursorParser; import com.litesuits.orm.db.model.ColumnsValue; import com.litesuits.orm.db.model.EntityTable; import com.litesuits.orm.db.model.MapInfo; import com.litesuits.orm.db.model.MapInfo.MapTable; import com.litesuits.orm.db.model.Property; import com.litesuits.orm.db.utils.ClassUtil; import com.litesuits.orm.db.utils.DataUtil; import com.litesuits.orm.db.utils.FieldUtil; import com.litesuits.orm.log.OrmLog; import java.io.IOException; import java.io.Serializable; import java.util.*; /** * sql语句构造与执行 * * @author mty * @date 2013-6-14下午7:48:34 */ public class SQLStatement implements Serializable { private static final long serialVersionUID = -3790876762607683712L; private static final String TAG = SQLStatement.class.getSimpleName(); public static final short NONE = -1; public static final short NORMAL = 0; public static final int IN_TOP_LIMIT = 999; /** * sql语句 */ public String sql; /** * sql语句中占位符对应的参数 */ public Object[] bindArgs; /** * sql语句执行者,私有(private)。 */ private SQLiteStatement mStatement; public SQLStatement() {} public SQLStatement(String sql, Object[] args) { this.sql = sql; this.bindArgs = args; } /** * 给sql语句的占位符(?)按序绑定值 * * @param i The 1-based index to the parameter to bind null to */ protected void bind(int i, Object o) throws IOException { if (o == null) { mStatement.bindNull(i); } else if (o instanceof CharSequence || o instanceof Boolean || o instanceof Character) { mStatement.bindString(i, String.valueOf(o)); } else if (o instanceof Float || o instanceof Double) { mStatement.bindDouble(i, ((Number) o).doubleValue()); } else if (o instanceof Number) { mStatement.bindLong(i, ((Number) o).longValue()); } else if (o instanceof Date) { mStatement.bindLong(i, ((Date) o).getTime()); } else if (o instanceof byte[]) { mStatement.bindBlob(i, (byte[]) o); } else if (o instanceof Serializable) { mStatement.bindBlob(i, DataUtil.objectToByte(o)); } else { mStatement.bindNull(i); } } /** * 插入数据,未传入实体所以不可以为之注入ID。 */ public long execInsert(SQLiteDatabase db) throws IOException, IllegalAccessException { return execInsertWithMapping(db, null, null); } /** * 插入数据,并为实体对象为之注入ID(如果需要)。 */ public long execInsert(SQLiteDatabase db, Object entity) throws IOException, IllegalAccessException { return execInsertWithMapping(db, entity, null); } /** * 插入数据,为其注入ID(如果需要),关系表也一并处理。 */ public long execInsertWithMapping(SQLiteDatabase db, Object entity, TableManager tableManager) throws IllegalAccessException, IOException { printSQL(); mStatement = db.compileStatement(sql); Object keyObj = null; if (!Checker.isEmpty(bindArgs)) { keyObj = bindArgs[0]; for (int i = 0; i < bindArgs.length; i++) { bind(i + 1, bindArgs[i]); } } //OrmLog.i(TAG, "SQL Execute bind over "); long rowID = NONE; try { rowID = mStatement.executeInsert(); } finally { realease(); } //OrmLog.i(TAG, "SQL Execute insert over "); if (OrmLog.isPrint) { OrmLog.i(TAG, "SQL Execute Insert RowID --> " + rowID + " sql: " + sql); } if (entity != null) { FieldUtil.setKeyValueIfneed(entity, TableManager.getTable(entity).key, keyObj, rowID); } if (tableManager != null) { mapRelationToDb(entity, true, true, db, tableManager); } return rowID; } /** * 执行批量插入 */ public int execInsertCollection(SQLiteDatabase db, Collection<?> list) { return execInsertCollectionWithMapping(db, list, null); } public int execInsertCollectionWithMapping(SQLiteDatabase db, Collection<?> list, TableManager tableManager) { printSQL(); db.beginTransaction(); if (OrmLog.isPrint) { OrmLog.i(TAG, "----> BeginTransaction[insert col]"); } EntityTable table = null; try { mStatement = db.compileStatement(sql); Iterator<?> it = list.iterator(); boolean mapTableCheck = true; while (it.hasNext()) { mStatement.clearBindings(); Object obj = it.next(); if (table == null) { table = TableManager.getTable(obj); } int j = 1; Object keyObj = null; if (table.key != null) { keyObj = FieldUtil.getAssignedKeyObject(table.key, obj); bind(j++, keyObj); } if (!Checker.isEmpty(table.pmap)) { // 第一个是主键。其他属性从2开始。 for (Property p : table.pmap.values()) { bind(j++, FieldUtil.get(p.field, obj)); } } long rowID = mStatement.executeInsert(); FieldUtil.setKeyValueIfneed(obj, table.key, keyObj, rowID); if (tableManager != null) { mapRelationToDb(obj, true, mapTableCheck, db, tableManager); mapTableCheck = false; } } if (OrmLog.isPrint) { OrmLog.i(TAG, "Exec insert [" + list.size() + "] rows , SQL: " + sql); } db.setTransactionSuccessful(); if (OrmLog.isPrint) { OrmLog.i(TAG, "----> BeginTransaction[insert col] Successful"); } return list.size(); } catch (Exception e) { if (OrmLog.isPrint) { OrmLog.e(TAG, "----> BeginTransaction[insert col] Failling"); } e.printStackTrace(); } finally { realease(); db.endTransaction(); } return NONE; } /** * 执行更新单个数据,返回受影响的行数 */ public int execUpdate(SQLiteDatabase db) throws IOException { return execUpdateWithMapping(db, null, null); } /** * 执行更新单个数据,返回受影响的行数 */ public int execUpdateWithMapping(SQLiteDatabase db, Object entity, TableManager tableManager) throws IOException { printSQL(); mStatement = db.compileStatement(sql); if (!Checker.isEmpty(bindArgs)) { for (int i = 0; i < bindArgs.length; i++) { bind(i + 1, bindArgs[i]); } } int rows = NONE; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { mStatement.execute(); rows = NORMAL; } else { rows = mStatement.executeUpdateDelete(); } realease(); if (OrmLog.isPrint) { OrmLog.i(TAG, "SQL Execute update, changed rows --> " + rows); } if (tableManager != null && entity != null) { mapRelationToDb(entity, true, true, db, tableManager); } return rows; } /** * 执行批量更新 */ public int execUpdateCollection(SQLiteDatabase db, Collection<?> list, ColumnsValue cvs) { return execUpdateCollectionWithMapping(db, list, cvs, null); } /** * 执行批量更新 */ public int execUpdateCollectionWithMapping(SQLiteDatabase db, Collection<?> list, ColumnsValue cvs, TableManager tableManager) { printSQL(); db.beginTransaction(); if (OrmLog.isPrint) { OrmLog.d(TAG, "----> BeginTransaction[update col]"); } try { mStatement = db.compileStatement(sql); Iterator<?> it = list.iterator(); boolean mapTableCheck = true; EntityTable table = null; while (it.hasNext()) { mStatement.clearBindings(); Object obj = it.next(); if (table == null) { table = TableManager.getTable(obj); } bindArgs = SQLBuilder.buildUpdateSqlArgsOnly(obj, cvs); if (!Checker.isEmpty(bindArgs)) { for (int i = 0; i < bindArgs.length; i++) { bind(i + 1, bindArgs[i]); } } mStatement.execute(); if (tableManager != null) { mapRelationToDb(obj, true, mapTableCheck, db, tableManager); mapTableCheck = false; } } if (OrmLog.isPrint) { OrmLog.i(TAG, "Exec update [" + list.size() + "] rows , SQL: " + sql); } db.setTransactionSuccessful(); if (OrmLog.isPrint) { OrmLog.d(TAG, "----> BeginTransaction[update col] Successful"); } return list.size(); } catch (Exception e) { if (OrmLog.isPrint) { OrmLog.e(TAG, "----> BeginTransaction[update col] Failling"); } e.printStackTrace(); } finally { realease(); db.endTransaction(); } return NONE; } /** * 删除语句执行,返回受影响的行数 */ public int execDelete(SQLiteDatabase db) throws IOException { return execDeleteWithMapping(db, null, null); } /** * 执行删操作.(excute delete ...),返回受影响的行数 * 并将关系映射删除 */ public int execDeleteWithMapping(final SQLiteDatabase db, Object entity, TableManager tableManager) throws IOException { printSQL(); mStatement = db.compileStatement(sql); if (bindArgs != null) { for (int i = 0; i < bindArgs.length; i++) { bind(i + 1, bindArgs[i]); } } int nums = NONE; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { mStatement.execute(); nums = NORMAL; } else { nums = mStatement.executeUpdateDelete(); } if (OrmLog.isPrint) { OrmLog.v(TAG, "SQL execute delete, changed rows--> " + nums); } realease(); if (tableManager != null && entity != null) { // 删除关系映射 mapRelationToDb(entity, false, false, db, tableManager); } return nums; } /** * 执行删操作.(excute delete ...),返回受影响的行数 * 并将关系映射删除 */ public int execDeleteCollection(final SQLiteDatabase db, final Collection<?> collection) throws IOException { return execDeleteCollectionWithMapping(db, collection, null); } /** * 执行删操作.(excute delete ...),返回受影响的行数 * 并将关系映射删除 */ public int execDeleteCollectionWithMapping(final SQLiteDatabase db, final Collection<?> collection, final TableManager tableManager) throws IOException { printSQL(); // 删除全部数据 mStatement = db.compileStatement(sql); if (bindArgs != null) { for (int i = 0; i < bindArgs.length; i++) { bind(i + 1, bindArgs[i]); } } int nums; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { mStatement.execute(); nums = collection.size(); } else { nums = mStatement.executeUpdateDelete(); } if (OrmLog.isPrint) { OrmLog.v(TAG, "SQL execute delete, changed rows --> " + nums); } realease(); if (tableManager != null) { // 删除关系映射 Boolean suc = Transaction.execute(db, new Transaction.Worker<Boolean>() { @Override public Boolean doTransaction(SQLiteDatabase db) throws Exception { boolean mapTableCheck = true; for (Object o : collection) { // 删除关系映射 mapRelationToDb(o, false, mapTableCheck, db, tableManager); mapTableCheck = false; } return true; } }); if (OrmLog.isPrint) { OrmLog.i(TAG, "Exec delete collection mapping: " + ((suc != null && suc) ? "成功" : "失败")); } } return nums; } /** * 执行create,drop table 等 */ public boolean execute(SQLiteDatabase db) { printSQL(); try { mStatement = db.compileStatement(sql); if (bindArgs != null) { for (int i = 0; i < bindArgs.length; i++) { bind(i + 1, bindArgs[i]); } } mStatement.execute(); return true; } catch (Exception e) { e.printStackTrace(); } finally { realease(); } return false; } /** * Execute a statement that returns a 1 by 1 table with a numeric value. * For example, SELECT COUNT(*) FROM table; */ public long queryForLong(SQLiteDatabase db) { printSQL(); long count = 0; try { mStatement = db.compileStatement(sql); if (bindArgs != null) { for (int i = 0; i < bindArgs.length; i++) { bind(i + 1, bindArgs[i]); } } count = mStatement.simpleQueryForLong(); if (OrmLog.isPrint) { OrmLog.i(TAG, "SQL execute query for count --> " + count); } } catch (Exception e) { e.printStackTrace(); } finally { realease(); } return count; } /** * 执行查询 * 根据类信息读取数据库,取出全部本类的对象。 */ public <T> ArrayList<T> query(SQLiteDatabase db, final Class<T> claxx) { printSQL(); final ArrayList<T> list = new ArrayList<T>(); try { final EntityTable table = TableManager.getTable(claxx, false); Querier.doQuery(db, this, new CursorParser() { @Override public void parseEachCursor(SQLiteDatabase db, Cursor c) throws Exception { //long start = System.nanoTime(); T t = ClassUtil.newInstance(claxx); //Log.i(TAG, "parse new after " + ((System.nanoTime() - start)/1000)); //start = System.nanoTime(); DataUtil.injectDataToObject(c, t, table); //Log.i(TAG, "parse inject after " + ((System.nanoTime() - start)/1000)); list.add(t); } }); } catch (Exception e) { e.printStackTrace(); } return list; } /** * 执行查询 * 根据类信息读取数据库,取出本类的对象。 */ public <T> T queryOneEntity(SQLiteDatabase db, final Class<T> claxx) { printSQL(); final EntityTable table = TableManager.getTable(claxx, false); T t = Querier.doQuery(db, this, new CursorParser<T>() { T t; @Override public void parseEachCursor(SQLiteDatabase db, Cursor c) throws Exception { t = ClassUtil.newInstance(claxx); DataUtil.injectDataToObject(c, t, table); stopParse(); } @Override public T returnResult() { return t; } }); return t; } @Override public String toString() { return "SQLStatement [sql=" + sql + ", bindArgs=" + Arrays.toString(bindArgs) + ", mStatement=" + mStatement + "]"; } /*------------------------------ 私有方法 ------------------------------*/ /** * 重新映射关系到数据库 * * @param insertNew 仅在执行删除该实体时,此值为false */ private void mapRelationToDb(Object entity, final boolean insertNew, final boolean tableCheck, SQLiteDatabase db, final TableManager tableManager) { // 插入关系映射 final MapInfo mapTable = SQLBuilder.buildMappingInfo(entity, insertNew, tableManager); if (mapTable != null && !mapTable.isEmpty()) { Transaction.execute(db, new Transaction.Worker<Boolean>() { @Override public Boolean doTransaction(SQLiteDatabase db) throws Exception { if (insertNew && tableCheck) { for (MapTable table : mapTable.tableList) { tableManager.checkOrCreateMappingTable(db, table.name, table.column1, table.column2); } } if (mapTable.delOldRelationSQL != null) { for (SQLStatement st : mapTable.delOldRelationSQL) { long rowId = st.execDelete(db); if (OrmLog.isPrint) { OrmLog.v(TAG, "Exec delete mapping success, nums: " + rowId); } } } if (insertNew && mapTable.mapNewRelationSQL != null) { for (SQLStatement st : mapTable.mapNewRelationSQL) { long rowId = st.execInsert(db); if (OrmLog.isPrint) { OrmLog.v(TAG, "Exec save mapping success, nums: " + rowId); } } } return true; } }); } } private void printSQL() { if (OrmLog.isPrint) { OrmLog.d(TAG, "SQL Execute: [" + sql + "] ARGS--> " + Arrays.toString(bindArgs)); } } private void realease() { if (mStatement != null) { mStatement.close(); } //sql = null; bindArgs = null; mStatement = null; } }