package cn.com.iresearch.mvideotracker.db;
import cn.com.iresearch.mvideotracker.db.sqlite.CursorUtils;
import cn.com.iresearch.mvideotracker.db.sqlite.DbModel;
import cn.com.iresearch.mvideotracker.db.sqlite.SqlBuilder;
import cn.com.iresearch.mvideotracker.db.sqlite.SqlInfo;
import cn.com.iresearch.mvideotracker.db.table.KeyValue;
import cn.com.iresearch.mvideotracker.db.table.ManyToOne;
import cn.com.iresearch.mvideotracker.db.table.OneToMany;
import cn.com.iresearch.mvideotracker.db.table.TableInfo;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
public class FinalDb
{
private static final String TAG = "FinalDb";
private static HashMap<String, FinalDb> daoMap = new HashMap<String, FinalDb>();
private SQLiteDatabase db;
private DaoConfig config;
private FinalDb(DaoConfig config)
{
if (config == null)
throw new RuntimeException("daoConfig is null");
if (config.getContext() == null)
throw new RuntimeException("android context is null");
this.db = new SqliteDbHelper(config.getContext().getApplicationContext(), config.getDbName(), config.getDbVersion(), config.getDbUpdateListener()).getWritableDatabase();
this.config = config;
}
private synchronized static FinalDb getInstance(DaoConfig daoConfig)
{
FinalDb dao = daoMap.get(daoConfig.getDbName());
if (dao == null)
{
dao = new FinalDb(daoConfig);
daoMap.put(daoConfig.getDbName(), dao);
}
return dao;
}
public static FinalDb create(Context context)
{
DaoConfig config = new DaoConfig();
config.setContext(context);
return getInstance(config);
}
public static FinalDb create(Context context, boolean isDebug)
{
DaoConfig config = new DaoConfig();
config.setContext(context);
config.setDebug(isDebug);
return getInstance(config);
}
public static FinalDb create(Context context, String dbName)
{
DaoConfig config = new DaoConfig();
config.setContext(context);
config.setDbName(dbName);
return getInstance(config);
}
public static FinalDb create(Context context, String dbName, boolean isDebug)
{
DaoConfig config = new DaoConfig();
config.setContext(context);
config.setDbName(dbName);
config.setDebug(isDebug);
return getInstance(config);
}
public static FinalDb create(Context context, String dbName, boolean isDebug, int dbVersion, DbUpdateListener dbUpdateListener)
{
DaoConfig config = new DaoConfig();
config.setContext(context);
config.setDbName(dbName);
config.setDebug(isDebug);
config.setDbVersion(dbVersion);
config.setDbUpdateListener(dbUpdateListener);
return getInstance(config);
}
public static FinalDb create(DaoConfig daoConfig)
{
return getInstance(daoConfig);
}
/**
* 保存一个java对象到数据库
*
* @param entity
*/
public void save(Object entity)
{
checkTableExist(entity.getClass());
exeSqlInfo(SqlBuilder.buildInsertSql(entity));
}
public boolean saveBindId(Object entity)
{
checkTableExist(entity.getClass());
List<KeyValue> entityKvList = SqlBuilder.getSaveKeyValueListByEntity(entity);
if (entityKvList != null && entityKvList.size() > 0)
{
TableInfo tf = TableInfo.get(entity.getClass());
ContentValues cv = new ContentValues();
insertContentValues(entityKvList, cv);
Long id = db.insert(tf.getTableName(), null, cv);
if (id == -1)
return false;
tf.getId().setValue(entity, id);
return true;
}
return false;
}
private void insertContentValues(List<KeyValue> list, ContentValues cv)
{
if (list != null && cv != null)
{
for (KeyValue kv : list)
{
cv.put(kv.getKey(), kv.getValue().toString());
}
} else
{
Log.w(TAG, "insertContentValues: List<KeyValue> is empty or ContentValues is empty!");
}
}
public void update(Object entity)
{
checkTableExist(entity.getClass());
exeSqlInfo(SqlBuilder.getUpdateSqlAsSqlInfo(entity));
}
public void update(Object entity, String strWhere)
{
checkTableExist(entity.getClass());
exeSqlInfo(SqlBuilder.getUpdateSqlAsSqlInfo(entity, strWhere));
}
public void delete(Object entity)
{
checkTableExist(entity.getClass());
exeSqlInfo(SqlBuilder.buildDeleteSql(entity));
}
public void deleteById(Class<?> clazz, Object id)
{
checkTableExist(clazz);
exeSqlInfo(SqlBuilder.buildDeleteSql(clazz, id));
}
/**
* 条件为空时,删除所有数据
*
* @param clazz
* @param strWhere
*/
public void deleteByWhere(Class<?> clazz, String strWhere)
{
checkTableExist(clazz);
String sql = SqlBuilder.buildDeleteSql(clazz, strWhere);
debugSql(sql);
db.execSQL(sql);
}
private void exeSqlInfo(SqlInfo sqlInfo)
{
if (sqlInfo != null)
{
debugSql(sqlInfo.getSql());
db.execSQL(sqlInfo.getSql(), sqlInfo.getBindArgsAsArray());
} else
{
Log.e(TAG, "sava error:sqlInfo is null");
}
}
public <T> T findById(Object id, Class<T> clazz)
{
checkTableExist(clazz);
SqlInfo sqlInfo = SqlBuilder.getSelectSqlAsSqlInfo(clazz, id);
if (sqlInfo != null)
{
debugSql(sqlInfo.getSql());
Cursor cursor = db.rawQuery(sqlInfo.getSql(), sqlInfo.getBindArgsAsStringArray());
try
{
if (cursor.moveToNext())
{
return CursorUtils.getEntity(cursor, clazz);
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
cursor.close();
}
}
return null;
}
public <T> T findWithManyToOneById(Object id, Class<T> clazz)
{
checkTableExist(clazz);
String sql = SqlBuilder.getSelectSQL(clazz, id);
debugSql(sql);
DbModel dbModel = findDbModelBySQL(sql);
if (dbModel != null)
{
T entity = CursorUtils.dbModel2Entity(dbModel, clazz);
if (entity != null)
{
try
{
Collection<ManyToOne> manys = TableInfo.get(clazz).manyToOneMap.values();
for (ManyToOne many : manys)
{
Object obj = dbModel.get(many.getColumn());
if (obj != null)
{
@SuppressWarnings("unchecked")
T manyEntity = (T) findById(Integer.valueOf(obj.toString()), many.getDataType());
if (manyEntity != null)
{
many.setValue(entity, manyEntity);
}
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
return entity;
}
return null;
}
public <T> T findWithManyToOneById(Object id, Class<T> clazz, Class<?>... findClass)
{
checkTableExist(clazz);
String sql = SqlBuilder.getSelectSQL(clazz, id);
debugSql(sql);
DbModel dbModel = findDbModelBySQL(sql);
if (dbModel != null)
{
T entity = CursorUtils.dbModel2Entity(dbModel, clazz);
if (entity != null)
{
try
{
Collection<ManyToOne> manys = TableInfo.get(clazz).manyToOneMap.values();
for (ManyToOne many : manys)
{
boolean isFind = false;
for (Class<?> mClass : findClass)
{
if (many.getManyClass() == mClass)
{
isFind = true;
break;
}
}
if (isFind)
{
@SuppressWarnings("unchecked")
T manyEntity = (T) findById(dbModel.get(many.getColumn()), many.getDataType());
if (manyEntity != null)
{
many.setValue(entity, manyEntity);
}
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
return entity;
}
return null;
}
public <T> T findWithOneToManyById(Object id, Class<T> clazz)
{
checkTableExist(clazz);
String sql = SqlBuilder.getSelectSQL(clazz, id);
debugSql(sql);
DbModel dbModel = findDbModelBySQL(sql);
if (dbModel != null)
{
T entity = CursorUtils.dbModel2Entity(dbModel, clazz);
if (entity != null)
{
try
{
Collection<OneToMany> ones = TableInfo.get(clazz).oneToManyMap.values();
for (OneToMany one : ones)
{
List<?> list = findAllByWhere(one.getOneClass(), one.getColumn() + "=" + id);
if (list != null)
{
one.setValue(entity, list);
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
return entity;
}
return null;
}
public <T> T findWithOneToManyById(Object id, Class<T> clazz, Class<?>... findClass)
{
checkTableExist(clazz);
String sql = SqlBuilder.getSelectSQL(clazz, id);
debugSql(sql);
DbModel dbModel = findDbModelBySQL(sql);
if (dbModel != null)
{
T entity = CursorUtils.dbModel2Entity(dbModel, clazz);
if (entity != null)
{
try
{
Collection<OneToMany> ones = TableInfo.get(clazz).oneToManyMap.values();
for (OneToMany one : ones)
{
boolean isFind = false;
for (Class<?> mClass : findClass)
{
if (one.getOneClass().equals(mClass.getName()))
{
isFind = true;
break;
}
}
if (isFind)
{
List<?> list = findAllByWhere(one.getOneClass(), one.getColumn() + "=" + id);
if (list != null)
{
one.setValue(entity, list);
}
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
return entity;
}
return null;
}
public <T> List<T> findAll(Class<T> clazz)
{
checkTableExist(clazz);
return findAllBySql(clazz, SqlBuilder.getSelectSQL(clazz));
}
public <T> List<T> findAll(Class<T> clazz, String orderBy)
{
checkTableExist(clazz);
return findAllBySql(clazz, SqlBuilder.getSelectSQL(clazz) + " ORDER BY " + orderBy + " DESC");
}
public <T> List<T> findAllByWhere(Class<T> clazz, String strWhere)
{
checkTableExist(clazz);
return findAllBySql(clazz, SqlBuilder.getSelectSQLByWhere(clazz, strWhere));
}
public <T> List<T> findAllByWhere(Class<T> clazz, String strWhere, String orderBy)
{
checkTableExist(clazz);
return findAllBySql(clazz, SqlBuilder.getSelectSQLByWhere(clazz, strWhere) + " ORDER BY " + orderBy + " DESC");
}
private <T> List<T> findAllBySql(Class<T> clazz, String strSQL)
{
checkTableExist(clazz);
debugSql(strSQL);
Cursor cursor = db.rawQuery(strSQL, null);
try
{
List<T> list = new ArrayList<T>();
while (cursor.moveToNext())
{
T t = CursorUtils.getEntity(cursor, clazz);
list.add(t);
}
return list;
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if (cursor != null)
cursor.close();
cursor = null;
}
return null;
}
public DbModel findDbModelBySQL(String strSQL)
{
debugSql(strSQL);
Cursor cursor = db.rawQuery(strSQL, null);
try
{
if (cursor.moveToNext())
{
return CursorUtils.getDbModel(cursor);
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
cursor.close();
}
return null;
}
public List<DbModel> findDbModelListBySQL(String strSQL)
{
debugSql(strSQL);
Cursor cursor = db.rawQuery(strSQL, null);
List<DbModel> dbModelList = new ArrayList<DbModel>();
try
{
while (cursor.moveToNext())
{
dbModelList.add(CursorUtils.getDbModel(cursor));
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
cursor.close();
}
return dbModelList;
}
/**
* 如果不存在,创建该表
*
* @param clazz
*/
private void checkTableExist(Class<?> clazz)
{
if (!tableIsExist(TableInfo.get(clazz)))
{
String sql = SqlBuilder.getCreatTableSQL(clazz);
debugSql(sql);
db.execSQL(sql);
}
}
private boolean tableIsExist(TableInfo table)
{
if (table.isCheckDatabese())
return true;
Cursor cursor = null;
try
{
String sql = "SELECT COUNT(*) AS c FROM sqlite_master WHERE type ='table' AND name ='" + table.getTableName() + "' ";
debugSql(sql);
cursor = db.rawQuery(sql, null);
if (cursor != null && cursor.moveToNext())
{
int count = cursor.getInt(0);
if (count > 0)
{
table.setCheckDatabese(true);
return true;
}
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if (cursor != null)
cursor.close();
cursor = null;
}
return false;
}
private void debugSql(String sql)
{
if (config != null && config.isDebug())
android.util.Log.d("Debug SQL", ">>>>>> " + sql);
}
public static class DaoConfig
{
private Context context = null;
private String dbName = "mAppTracker.db";
private int dbVersion = 1;
private boolean debug = true;
private DbUpdateListener dbUpdateListener;
public Context getContext()
{
return context;
}
public void setContext(Context context)
{
this.context = context;
}
public String getDbName()
{
return dbName;
}
public void setDbName(String dbName)
{
this.dbName = dbName;
}
public int getDbVersion()
{
return dbVersion;
}
public void setDbVersion(int dbVersion)
{
this.dbVersion = dbVersion;
}
public boolean isDebug()
{
return debug;
}
public void setDebug(boolean debug)
{
this.debug = debug;
}
public DbUpdateListener getDbUpdateListener()
{
return dbUpdateListener;
}
public void setDbUpdateListener(DbUpdateListener dbUpdateListener)
{
this.dbUpdateListener = dbUpdateListener;
}
}
class SqliteDbHelper extends SQLiteOpenHelper
{
private DbUpdateListener mDbUpdateListener;
public SqliteDbHelper(Context context, String name, int version, DbUpdateListener dbUpdateListener)
{
super(context, name, null, version);
this.mDbUpdateListener = dbUpdateListener;
}
public void onCreate(SQLiteDatabase db)
{
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
if (mDbUpdateListener != null)
{
mDbUpdateListener.onUpgrade(db, oldVersion, newVersion);
} else
{
Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type ='table'", null);
if (cursor != null)
{
while (cursor.moveToNext())
{
db.execSQL("DROP TABLE " + cursor.getString(0));
}
}
if (cursor != null)
{
cursor.close();
cursor = null;
}
}
}
}
public interface DbUpdateListener
{
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
}
}