package com.yc.database.manager; import android.annotation.SuppressLint; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import java.io.Serializable; import java.util.Date; import com.yc.database.bean.BindSQL; import com.yc.database.utils.DBLog; import com.yc.database.utils.DateUtil; /** *
 *     @author yangchong
 *     email  : yangchong211@163.com
 *     time  : 2017/8/6
 *     desc  : SQL语句执行器
 *     revise:
 * 
*/ public class SQLExecuteManager implements Serializable { /** * uid */ private static final long serialVersionUID = 1L; /** * SQLite中的关键字 */ public static final String[] SQLITE_KEYWORDS = { "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE" }; /** * 数据库操作类 */ private SQLiteDatabase mSQLiteDataBase; public SQLExecuteManager(SQLiteDatabase mSQLiteDataBase) { super(); this.mSQLiteDataBase = mSQLiteDataBase; } /** * 开启一个事务(事务开始) * 在事务代码执行完成后,必须要执行successTransaction()将事务标记为成功 * 在代码的最后必须要执行endTransaction()来结束当前事务,如果事务成功则提交事务,否则回滚事务 *
	 *   db.beginTransaction();
	 *   try {
	 *     ...
	 *     db.setTransactionSuccessful();
	 *   } finally {
	 *     db.endTransaction();
	 *   }
	 * 
*/ public void beginTransaction() { this.mSQLiteDataBase.beginTransaction(); } /** * 标记当前事务成功 */ public void successTransaction() { this.mSQLiteDataBase.setTransactionSuccessful(); } /** * 结束当前事务,当事物被标记成功后,此操作会提交事务,否则会回滚事务 */ public void endTransaction() { this.mSQLiteDataBase.endTransaction(); } /** * 执行指定无返回值的单条SQL语句,如建表、创建数据库等 * @param sql 执行sql */ public void execSQL(String sql) { DBLog.debug(sql); this.mSQLiteDataBase.execSQL(sql); } /** * 插入一条记录,返回该记录的rowId * @param sql * @param args * @return 插入失败返回-1,成功返回rowId */ public long insert(String sql, Object[] args) { long rowId = -1; SQLiteStatement statement = this.mSQLiteDataBase.compileStatement(sql); try { if(args != null) { for(int i = 0; i < args.length; i++) { bindArgs(statement, i + 1, args[i]); } } rowId = statement.executeInsert(); DBLog.debug(sql, args); } finally { statement.close(); } return rowId; } /** * 根据BindSQL进行插入数据 * @param bindSQL * @return * @throws Exception */ public long insert(BindSQL bindSQL) { if (bindSQL==null){ return -1; } String sql = bindSQL.getSql(); Object[] bindArgs = bindSQL.getBindArgs(); return insert(sql, bindArgs); } /** * 绑定参数 * @param statement * @param position * @param args */ private void bindArgs(SQLiteStatement statement, int position, Object args) { int type = FieldTypeManager.getValueType(args); switch(type) { case FieldTypeManager.VALUE_TYPE_NULL: statement.bindNull(position); break; case FieldTypeManager.BASE_TYPE_BYTE_ARRAY: statement.bindBlob(position, (byte[])args); break; case FieldTypeManager.BASE_TYPE_CHAR: case FieldTypeManager.BASE_TYPE_STRING: statement.bindString(position, args.toString()); break; case FieldTypeManager.BASE_TYPE_DATE: statement.bindString(position, DateUtil.formatDatetime((Date) args)); break; case FieldTypeManager.BASE_TYPE_DOUBLE: case FieldTypeManager.BASE_TYPE_FLOAT: statement.bindDouble(position, Double.parseDouble(args.toString())); break; case FieldTypeManager.BASE_TYPE_INT: case FieldTypeManager.BASE_TYPE_LONG: case FieldTypeManager.BASE_TYPE_SHORT: statement.bindLong(position, Long.parseLong(args.toString())); break; case FieldTypeManager.NOT_BASE_TYPE: throw new IllegalArgumentException("未知参数类型,请检查绑定参数"); } } /** * 删除指定表 * @param tableName * @throws Exception */ public void dropTable(String tableName) { String sql = "DROP TABLE IF EXISTS " + tableName; execSQL(sql); } /** * 删除,表名不能使用占位符 * @param bindSQL */ public void delete(BindSQL bindSQL) { updateOrDelete(bindSQL.getSql(), bindSQL.getBindArgs()); } /** * 删除,表名不能使用占位符 * @param sql 删除语句(参数使用占位符) * @param args 占位符参数 */ @SuppressLint("NewApi") public void updateOrDelete(String sql, Object[] args) { SQLiteStatement statement = mSQLiteDataBase.compileStatement(sql); try { if(args != null) { for(int i = 0; i < args.length; i++) { bindArgs(statement, i + 1, args[i]); } } DBLog.debug(sql, args); statement.executeUpdateDelete(); } finally { statement.close(); } } /** * 删除(对于表名需要动态获取的,此方法非常适合) * @param tableName 要删除的数据表 * @param whereClause where后面的条件句(delete from XXX where XXX),参数使用占位符 * @param whereArgs where子句后面的占位符参数 */ public void delete(String tableName, String whereClause, String[] whereArgs) { DBLog.debug("{SQL:DELETE FROM " + tableName + " WHERE " + whereClause + ",PARAMS:" + whereArgs + "}"); mSQLiteDataBase.delete(tableName, whereClause, whereArgs); } /** * 更新 * @param bindSQL */ public void update(BindSQL bindSQL) { updateOrDelete(bindSQL.getSql(), bindSQL.getBindArgs()); } /** * 根据SQL进行查询 * @param sql * @return */ public Cursor query(String sql) { return query(sql, null); } /** * 执行绑定语句 * 运行一个预置的SQL语句,返回带游标的数据集(与query的语句最大的区别 = 防止SQL注入) * @param sql sql语句 * @param whereArgs 搜索条件 * @return */ public Cursor query(String sql, String[] whereArgs) { DBLog.debug("{SQL:" + sql + ",PARAMS:" + whereArgs + "}"); return this.mSQLiteDataBase.rawQuery(sql, whereArgs); } /** * 根据BindSQL查询 * @param bindSQL * @return */ public Cursor query(BindSQL bindSQL) { return query(bindSQL.getSql(), (String[])bindSQL.getBindArgs()); } @Deprecated public Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) { // 查询指定的数据表返回一个带游标的数据集。 // 各参数说明: // table:表名称 // colums:列名称数组 // selection:条件子句,相当于where // selectionArgs:条件语句的参数数组 // groupBy:分组 // having:分组条件 // orderBy:排序类 // limit:分页查询的限制 return this.mSQLiteDataBase.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit); } }