package com.litesuits.orm.db.impl;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.litesuits.orm.LiteOrm;
import com.litesuits.orm.db.DataBaseConfig;
import com.litesuits.orm.db.TableManager;
import com.litesuits.orm.db.assit.*;
import com.litesuits.orm.db.assit.Transaction.Worker;
import com.litesuits.orm.db.model.*;
import com.litesuits.orm.db.utils.ClassUtil;
import com.litesuits.orm.db.utils.DataUtil;
import com.litesuits.orm.db.utils.FieldUtil;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
/**
* 数据SQLite操作关联实现
* 可查阅 <a href="http://www.sqlite.org/lang.html">SQLite操作指南</a>
*
* @author MaTianyu
* @date 2015-03-13
*/
public final class CascadeSQLiteImpl extends LiteOrm {
public static final String TAG = CascadeSQLiteImpl.class.getSimpleName();
protected CascadeSQLiteImpl(LiteOrm dataBase) {
super(dataBase);
}
private CascadeSQLiteImpl(DataBaseConfig config) {
super(config);
}
public synchronized static LiteOrm newInstance(DataBaseConfig config) {
return new CascadeSQLiteImpl(config);
}
@Override
public LiteOrm single() {
if (otherDatabase == null) {
otherDatabase = new SingleSQLiteImpl(this);
}
return otherDatabase;
}
@Override
public LiteOrm cascade() {
return this;
}
@Override
public long save(final Object entity) {
acquireReference();
try {
SQLiteDatabase db = mHelper.getWritableDatabase();
Long rowID = Transaction.execute(db, new Worker<Long>() {
@Override
public Long doTransaction(SQLiteDatabase db) throws Exception {
HashMap<String, Integer> handleMap = new HashMap<String, Integer>();
return checkTableAndSaveRecursive(entity, db, handleMap);
}
});
return rowID == null ? SQLStatement.NONE : rowID;
} finally {
releaseReference();
}
}
@Override
public <T> int save(Collection<T> collection) {
acquireReference();
try {
return saveCollection(collection);
} finally {
releaseReference();
}
}
@Override
public long insert(Object entity) {
return insert(entity, null);
}
@Override
public long insert(final Object entity, final ConflictAlgorithm conflictAlgorithm) {
acquireReference();
try {
SQLiteDatabase db = mHelper.getWritableDatabase();
Long rowID = Transaction.execute(db, new Worker<Long>() {
@Override
public Long doTransaction(SQLiteDatabase db) throws Exception {
mTableManager.checkOrCreateTable(db, entity);
return insertRecursive(SQLBuilder.buildInsertSql(entity, conflictAlgorithm),
entity, db, new HashMap<String, Integer>());
}
});
return rowID == null ? SQLStatement.NONE : rowID;
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
@Override
public <T> int insert(Collection<T> collection) {
return insert(collection, null);
}
@Override
public <T> int insert(Collection<T> collection, ConflictAlgorithm conflictAlgorithm) {
acquireReference();
try {
return insertCollection(collection, conflictAlgorithm);
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
@Override
public int update(Object entity) {
return update(entity, null, null);
}
@Override
public int update(Object entity, ConflictAlgorithm conflictAlgorithm) {
return update(entity, null, conflictAlgorithm);
}
@Override
public int update(final Object entity, final ColumnsValue cvs, final ConflictAlgorithm conflictAlgorithm) {
acquireReference();
try {
SQLiteDatabase db = mHelper.getWritableDatabase();
Integer rowID = Transaction.execute(db, new Worker<Integer>() {
@Override
public Integer doTransaction(SQLiteDatabase db) throws Exception {
HashMap<String, Integer> handleMap = new HashMap<String, Integer>();
SQLStatement stmt = SQLBuilder.buildUpdateSql(entity, cvs, conflictAlgorithm);
mTableManager.checkOrCreateTable(db, entity);
return updateRecursive(stmt, entity, db, handleMap);
}
});
return rowID == null ? SQLStatement.NONE : rowID;
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
@Override
public <T> int update(Collection<T> collection) {
return update(collection, null, null);
}
@Override
public <T> int update(Collection<T> collection, ConflictAlgorithm conflictAlgorithm) {
return update(collection, null, conflictAlgorithm);
}
@Override
public <T> int update(Collection<T> collection, ColumnsValue cvs, ConflictAlgorithm conflictAlgorithm) {
acquireReference();
try {
return updateCollection(collection, cvs, conflictAlgorithm);
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
/**
* 主动删除其mapping数据
*/
@Override
public int delete(final Object entity) {
acquireReference();
try {
SQLiteDatabase db = mHelper.getWritableDatabase();
Integer rowID = Transaction.execute(db, new Worker<Integer>() {
@Override
public Integer doTransaction(SQLiteDatabase db) throws Exception {
HashMap<String, Integer> handleMap = new HashMap<String, Integer>();
return checkTableAndDeleteRecursive(entity, db, handleMap);
}
});
if (rowID != null) {
return rowID;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
@Override
public <T> int delete(Class<T> claxx) {
return deleteAll(claxx);
}
@Override
public <T> int delete(final Collection<T> collection) {
acquireReference();
try {
return deleteCollectionIfTableHasCreated(collection);
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
@Override
public <T> int delete(Class<T> claxx, WhereBuilder where) {
acquireReference();
try {
EntityTable table = TableManager.getTable(claxx);
List<T> list = query(QueryBuilder.create(claxx).columns(new String[]{table.key.column}).where(where));
delete(list);
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
@Override
public int delete(WhereBuilder where) {
acquireReference();
try {
EntityTable table = TableManager.getTable(where.getTableClass());
List<?> list = query(QueryBuilder
.create(where.getTableClass())
.columns(new String[]{table.key.column})
.where(where));
deleteCollectionIfTableHasCreated(list);
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return SQLStatement.NONE;
}
@Override
public <T> int deleteAll(Class<T> claxx) {
acquireReference();
try {
final EntityTable table = TableManager.getTable(claxx);
List<T> list = query(QueryBuilder.create(claxx).columns(new String[]{table.key.column}));
return delete(list);
} finally {
releaseReference();
}
}
/**
* 删除从[start,end]的数据
* 此方法暂不会删除关联映射表里的关系数据
*/
@Override
public <T> int delete(Class<T> claxx, long start, long end, String orderAscColumn) {
acquireReference();
try {
if (start < 0 || end < start) {
throw new RuntimeException("start must >=0" +
" and smaller than end");
}
if (start != 0) {
start -= 1;
}
end = end == Integer.MAX_VALUE ? -1 : end - start;
final EntityTable table = TableManager.getTable(claxx);
List<T> list = query(QueryBuilder
.create(claxx)
.limit(start + SQLBuilder.COMMA + end)
.appendOrderAscBy(orderAscColumn)
.columns(new String[]{table.key.column}));
return delete(list);
} finally {
releaseReference();
}
}
@Override
public <T> ArrayList<T> query(Class<T> claxx) {
return checkTableAndQuery(claxx, new QueryBuilder<T>(claxx));
}
@Override
public <T> ArrayList<T> query(QueryBuilder<T> qb) {
return checkTableAndQuery(qb.getQueryClass(), qb);
}
@Override
public <T> T queryById(long id, Class<T> claxx) {
return queryById(String.valueOf(id), claxx);
}
@Override
public <T> T queryById(String id, Class<T> claxx) {
EntityTable table = TableManager.getTable(claxx);
ArrayList<T> list = checkTableAndQuery(claxx, new QueryBuilder<T>(claxx)
.whereEquals(table.key.column, String.valueOf(id)));
if (!Checker.isEmpty(list)) {
return list.get(0);
}
return null;
}
/* -------------------------------- 私有方法: 查询相关 -------------------------------- */
/**
* 过程:
* <p/>
* 1. 根据条件查找符合条件的所有当前对象
* 2. 遍历所有当前对象,遍历其所有关联对象,读取关系表 map:<key1, key2>
* 3. 如果是多对一,根据map查找key2的关联对象,赋给obj1
* 4. 如果是一对多,根据map查找key2的关联对象,反射实例化obj1的容器,关联对象放入。
* 5. 并对关联对象递归此过程
*/
private <T> ArrayList<T> checkTableAndQuery(final Class<T> claxx, QueryBuilder builder) {
acquireReference();
final ArrayList<T> list = new ArrayList<T>();
try {
final EntityTable table = TableManager.getTable(claxx, false);
if (mTableManager.isSQLTableCreated(table.name)) {
final HashMap<String, Object> entityMap = new HashMap<String, Object>();
final HashMap<String, Integer> queryMap = new HashMap<String, Integer>();
SQLiteDatabase db = mHelper.getReadableDatabase();
Querier.doQuery(db, builder.createStatement(), new Querier.CursorParser() {
@Override
public void parseEachCursor(SQLiteDatabase db, Cursor c) throws Exception {
T t = ClassUtil.newInstance(claxx);
DataUtil.injectDataToObject(c, t, table);
list.add(t);
entityMap.put(table.name + FieldUtil.get(table.key.field, t), t);
}
});
for (T t : list) {
queryForMappingRecursive(t, db, queryMap, entityMap);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
releaseReference();
}
return list;
}
/**
* 循环遍历查找当前实体的关联实体
*/
private void queryForMappingRecursive(Object obj1, SQLiteDatabase db, HashMap<String, Integer> queryMap,
HashMap<String, Object> entityMap)
throws IllegalAccessException, InstantiationException {
final EntityTable table1 = TableManager.getTable(obj1);
Object key1 = FieldUtil.getAssignedKeyObject(table1.key, obj1);
String key = table1.name + key1;
if (queryMap.get(key) == null) {
queryMap.put(key, 1);
if (table1.mappingList != null) {
for (MapProperty mp : table1.mappingList) {
if (mp.isToOne()) {
queryMapToOne(table1, key1, obj1, mp.field, db, queryMap, entityMap);
} else if (mp.isToMany()) {
queryMapToMany(table1, key1, obj1, mp.field, db, queryMap, entityMap);
}
}
}
}
}
/**
* 查找N对一关系的实体
*/
private void queryMapToOne(final EntityTable table1, Object key1, Object obj1,
Field field, SQLiteDatabase db, HashMap<String, Integer> queryMap,
HashMap<String, Object> entityMap)
throws IllegalAccessException, InstantiationException {
final EntityTable table2 = TableManager.getTable(field.getType());
if (mTableManager.isSQLMapTableCreated(table1.name, table2.name)) {
SQLStatement relationSql = SQLBuilder.buildQueryRelationSql(table1, table2, key1);
final RelationKey relation = new RelationKey();
Querier.doQuery(db, relationSql, new Querier.CursorParser() {
@Override
public void parseEachCursor(SQLiteDatabase db, Cursor c) throws Exception {
relation.key1 = c.getString(c.getColumnIndex(table1.name));
relation.key2 = c.getString(c.getColumnIndex(table2.name));
stopParse();
}
});
if (relation.isOK()) {
String key = table2.name + relation.key2;
Object obj2 = entityMap.get(key);
if (obj2 == null) {
SQLStatement entitySql = SQLBuilder.buildQueryMapEntitySql(table2, relation.key2);
obj2 = entitySql.queryOneEntity(db, table2.claxx);
entityMap.put(key, obj2);
}
if (obj2 != null) {
FieldUtil.set(field, obj1, obj2);
queryForMappingRecursive(obj2, db, queryMap, entityMap);
}
}
}
}
/**
* 查找N对关系的实体
*/
@SuppressWarnings("unchecked")
private void queryMapToMany(final EntityTable table1, Object key1, Object obj1,
Field field, SQLiteDatabase db, HashMap<String, Integer> queryMap,
final HashMap<String, Object> entityMap)
throws IllegalAccessException, InstantiationException {
final Class<?> class2;
if (Collection.class.isAssignableFrom(field.getType())) {
class2 = FieldUtil.getGenericType(field);
} else if (field.getType().isArray()) {
class2 = FieldUtil.getComponentType(field);
} else {
throw new RuntimeException("OneToMany and ManyToMany Relation, " +
"you must use collection or array object");
}
final EntityTable table2 = TableManager.getTable(class2);
if (mTableManager.isSQLMapTableCreated(table1.name, table2.name)) {
SQLStatement relationSql = SQLBuilder.buildQueryRelationSql(table1, table2, key1);
final ArrayList<String> key2List = new ArrayList<String>();
Querier.doQuery(db, relationSql, new Querier.CursorParser() {
@Override
public void parseEachCursor(SQLiteDatabase db, Cursor c) throws Exception {
key2List.add(c.getString(c.getColumnIndex(table2.name)));
}
});
if (!Checker.isEmpty(key2List)) {
final ArrayList<Object> allList2 = new ArrayList<Object>();
for (int i = key2List.size() - 1; i >= 0; i--) {
Object obj2 = entityMap.get(table2.name + key2List.get(i));
if (obj2 != null) {
allList2.add(obj2);
key2List.remove(i);
}
}
//final Class<?> class2 = compClass;
int i = 0, start = 0, end;
while (start < key2List.size()) {
int next = ++i * SQLStatement.IN_TOP_LIMIT;
end = Math.min(key2List.size(), next);
List<String> subList = key2List.subList(start, end);
start = next;
SQLStatement entitySql = QueryBuilder
.create(class2)
.whereIn(table2.key.column, subList.toArray(new String[subList.size()]))
.createStatement();
Querier.doQuery(db, entitySql, new Querier.CursorParser() {
@Override
public void parseEachCursor(SQLiteDatabase db, Cursor c) throws Exception {
Object t = ClassUtil.newInstance(class2);
DataUtil.injectDataToObject(c, t, table2);
allList2.add(t);
entityMap.put(table2.name + FieldUtil.get(table2.key.field, t), t);
}
});
}
if (!Checker.isEmpty(allList2)) {
if (Collection.class.isAssignableFrom(field.getType())) {
Collection coll = (Collection) ClassUtil.newCollectionForField(field);
coll.addAll(allList2);
FieldUtil.set(field, obj1, coll);
} else if (field.getType().isArray()) {
Object[] arrObj = (Object[]) ClassUtil.newArray(class2, allList2.size());
arrObj = allList2.toArray(arrObj);
FieldUtil.set(field, obj1, arrObj);
} else {
throw new RuntimeException("OneToMany and ManyToMany Relation, " +
"you must use collection or array object");
}
for (Object obj2 : allList2) {
queryForMappingRecursive(obj2, db, queryMap, entityMap);
}
}
}
}
}
/* -------------------------------- 私有方法: 集合操作相关 -------------------------------- */
/**
* 将集合更高效地存储下来
*
* @param collection any collection
* @return return size of collection if do successfully, -1 or not.
*/
private <T> int saveCollection(final Collection<T> collection) {
if (!Checker.isEmpty(collection)) {
SQLiteDatabase db = mHelper.getWritableDatabase();
Integer rowID = Transaction.execute(db, new Worker<Integer>() {
@Override
public Integer doTransaction(SQLiteDatabase db) throws Exception {
//0. 保存第一个实体
HashMap<String, Integer> handleMap = new HashMap<String, Integer>();
Iterator<T> iterator = collection.iterator();
Object entity = iterator.next();
SQLStatement stmt = SQLBuilder.buildReplaceSql(entity);
mTableManager.checkOrCreateTable(db, entity);
insertRecursive(stmt, entity, db, handleMap);
//1.0 保存剩余实体
while (iterator.hasNext()) {
entity = iterator.next();
//1.1 绑定对应值
stmt.bindArgs = SQLBuilder.buildInsertSqlArgsOnly(entity);
//1.2 保存当前实体
insertRecursive(stmt, entity, db, handleMap);
}
return collection.size();
}
});
if (rowID != null) {
return rowID;
}
}
return SQLStatement.NONE;
}
/**
* 将集合更高效地存储下来
*
* @param collection any collection
* @param conflictAlgorithm when conflict
* @return return size of collection if do successfully, -1 or not.
*/
private <T> int insertCollection(final Collection<T> collection, final ConflictAlgorithm conflictAlgorithm) {
if (!Checker.isEmpty(collection)) {
SQLiteDatabase db = mHelper.getWritableDatabase();
Integer rowID = Transaction.execute(db, new Worker<Integer>() {
@Override
public Integer doTransaction(SQLiteDatabase db) throws Exception {
//0. 保存第一个实体
HashMap<String, Integer> handleMap = new HashMap<String, Integer>();
Iterator<T> iterator = collection.iterator();
Object entity = iterator.next();
SQLStatement stmt = SQLBuilder.buildInsertSql(entity, conflictAlgorithm);
mTableManager.checkOrCreateTable(db, entity);
insertRecursive(stmt, entity, db, handleMap);
//1.0 保存剩余实体
while (iterator.hasNext()) {
//1.1 绑定对应值
entity = iterator.next();
//1.2 保存当前实体
stmt.bindArgs = SQLBuilder.buildInsertSqlArgsOnly(entity);
insertRecursive(stmt, entity, db, handleMap);
}
return collection.size();
}
});
if (rowID != null) {
return rowID;
}
}
return SQLStatement.NONE;
}
/**
* 将集合更高效地存储下来
*
* @param collection any collection
* @param conflictAlgorithm when conflict
* @return return size of collection if do successfully, -1 or not.
*/
private <T> int updateCollection(final Collection<T> collection, final ColumnsValue cvs,
final ConflictAlgorithm conflictAlgorithm) {
if (!Checker.isEmpty(collection)) {
SQLiteDatabase db = mHelper.getWritableDatabase();
Integer rowID = Transaction.execute(db, new Worker<Integer>() {
@Override
public Integer doTransaction(SQLiteDatabase db) throws Exception {
//0. 保存第一个实体
HashMap<String, Integer> handleMap = new HashMap<String, Integer>();
Iterator<T> iterator = collection.iterator();
Object entity = iterator.next();
SQLStatement stmt = SQLBuilder.buildUpdateSql(entity, cvs, conflictAlgorithm);
mTableManager.checkOrCreateTable(db, entity);
updateRecursive(stmt, entity, db, handleMap);
//1.0 保存剩余实体
while (iterator.hasNext()) {
//1.1 绑定对应值
entity = iterator.next();
//1.2 保存当前实体
stmt.bindArgs = SQLBuilder.buildUpdateSqlArgsOnly(entity, cvs);
updateRecursive(stmt, entity, db, handleMap);
}
return collection.size();
}
});
if (rowID != null) {
return rowID;
}
}
return SQLStatement.NONE;
}
/**
* 将集合更高效地删除
*
* @param collection any collection
* @return return size of collection if do successfully, -1 or not.
*/
private <T> int deleteCollectionIfTableHasCreated(final Collection<T> collection) {
if (!Checker.isEmpty(collection)) {
final Iterator<T> iterator = collection.iterator();
final Object entity = iterator.next();
EntityTable table = TableManager.getTable(entity);
if (mTableManager.isSQLTableCreated(table.name)) {
SQLiteDatabase db = mHelper.getWritableDatabase();
Integer rowID = Transaction.execute(db, new Worker<Integer>() {
@Override
public Integer doTransaction(SQLiteDatabase db) throws Exception {
//0. 删除第一个实体
HashMap<String, Integer> handleMap = new HashMap<String, Integer>();
SQLStatement stmt = SQLBuilder.buildDeleteSql(entity);
deleteRecursive(stmt, entity, db, handleMap);
//1.0 删除剩余实体
while (iterator.hasNext()) {
//1.1 绑定对应值
Object next = iterator.next();
//1.2 保存当前实体
stmt.bindArgs = getDeleteStatementArgs(next);
deleteRecursive(stmt, next, db, handleMap);
}
return collection.size();
}
});
if (rowID != null) {
return rowID;
}
}
}
return SQLStatement.NONE;
}
/**
* 获取被删除对象的参数
*/
public static Object[] getDeleteStatementArgs(Object entity) throws IllegalAccessException {
EntityTable table = TableManager.getTable(entity);
if (table.key != null) {
return new String[]{String.valueOf(FieldUtil.get(table.key.field, entity))};
} else if (!Checker.isEmpty(table.pmap)) {
Object[] args = new Object[table.pmap.size()];
int i = 0;
for (Property p : table.pmap.values()) {
args[i++] = FieldUtil.get(p.field, entity);
}
return args;
}
return null;
}
/* -------------------------------- 私有方法:增删改相关 -------------------------------- */
public static final int TYPE_INSERT = 1;
public static final int TYPE_UPDATE = 2;
public static final int TYPE_DELETE = 3;
/**
* 通过递归保存[该对象],以及该对象所有的[关联对象]以及它们的[映射关系]
*
* @param obj1 需要保存的对象
* @param db 可写数据库对象
* @return rowID of entity
*/
private long handleEntityRecursive(int type, SQLStatement stmt, Object obj1, SQLiteDatabase db,
HashMap<String, Integer> handleMap) throws Exception {
EntityTable table1 = TableManager.getTable(obj1);
Object key1 = FieldUtil.get(table1.key.field, obj1);
// 0. 若[当前实体]已存储过,不再操作
if (handleMap.get(table1.name + key1) != null) {
return SQLStatement.NONE;
}
// 1. 存储[当前实体]
long rowID = SQLStatement.NONE;
switch (type) {
case TYPE_INSERT:
rowID = stmt.execInsert(db, obj1);
key1 = FieldUtil.get(table1.key.field, obj1);
break;
case TYPE_UPDATE:
rowID = stmt.execUpdate(db);
break;
case TYPE_DELETE:
rowID = stmt.execDelete(db);
break;
default:
}
handleMap.put(table1.name + key1, 1);
// 2. 存储[关联实体]以及其[关系映射]
boolean insertNew = type != TYPE_DELETE;
handleMapping(key1, obj1, db, insertNew, handleMap);
return rowID;
}
/**
* 通过递归保更新[该对象],保存该对象所有的[关联对象]以及它们的[映射关系]
*
* @param obj1 需要保存的对象
* @param db 可写数据库对象
* @return rowID of entity
*/
private int updateRecursive(SQLStatement stmt, Object obj1, SQLiteDatabase db,
HashMap<String, Integer> handleMap) throws Exception {
EntityTable table1 = TableManager.getTable(obj1);
Object key1 = FieldUtil.get(table1.key.field, obj1);
// 0. 若[当前实体]已存储过,不再操作
if (handleMap.get(table1.name + key1) != null) {
return SQLStatement.NONE;
}
// 1. 更新[当前实体]
int rowID = stmt.execUpdate(db);
key1 = FieldUtil.get(table1.key.field, obj1);
handleMap.put(table1.name + key1, 1);
// 2. 存储[关联实体]以及其[关系映射]
handleMapping(key1, obj1, db, true, handleMap);
return rowID;
}
/**
* 通过递归删除[该对象],以及该对象所有的[关联对象]以及它们的[映射关系]
*
* @param obj1 需要保存的对象
* @param db 可写数据库对象
* @return rowID of entity
*/
private int deleteRecursive(SQLStatement stmt, Object obj1, SQLiteDatabase db,
HashMap<String, Integer> handleMap) throws Exception {
EntityTable table1 = TableManager.getTable(obj1);
Object key1 = FieldUtil.get(table1.key.field, obj1);
// 0. 若[当前实体]已删除过,不再操作
if (handleMap.get(table1.name + key1) != null) {
return SQLStatement.NONE;
}
// 1. 删除[当前实体]
int rowID = stmt.execDelete(db);
handleMap.put(table1.name + key1, 1);
// 2. 删除[关联实体]以及其[关系映射]
handleMapping(key1, obj1, db, false, handleMap);
return rowID;
}
/**
* 通过递归保存[该对象],以及该对象所有的[关联对象]以及它们的[映射关系]
*
* @param obj1 需要保存的对象
* @param db 可写数据库对象
* @return rowID of entity
*/
private long insertRecursive(SQLStatement stmt, Object obj1, SQLiteDatabase db,
HashMap<String, Integer> handleMap) throws Exception {
EntityTable table1 = TableManager.getTable(obj1);
Object key1 = FieldUtil.get(table1.key.field, obj1);
// 0. 若[当前实体]已存储过,不再操作
if (handleMap.get(table1.name + key1) != null) {
return SQLStatement.NONE;
}
// 1. 存储[当前实体]
long rowID = stmt.execInsert(db, obj1);
key1 = FieldUtil.get(table1.key.field, obj1);
handleMap.put(table1.name + key1, 1);
// 2. 存储[关联实体]以及其[关系映射]
handleMapping(key1, obj1, db, true, handleMap);
return rowID;
}
/* -------------------------------- 私有方法:处理关系 -------------------------------- */
/**
* 通过递归保存[该对象],以及该对象所有的[关联对象]以及它们的[映射关系]
*
* @param obj1 需要保存的对象
* @param db 可写数据库对象
* @return rowID of entity
*/
private long checkTableAndSaveRecursive(Object obj1, SQLiteDatabase db, HashMap<String, Integer> handleMap)
throws Exception {
mTableManager.checkOrCreateTable(db, obj1);
return insertRecursive(SQLBuilder.buildReplaceSql(obj1), obj1, db, handleMap);
}
/**
* 通过递归删除[该对象],以及该对象所有的[关联对象]以及它们的[映射关系]
*
* @param obj1 需要保存的对象
* @param db 可写数据库对象
* @return rowID of entity
*/
private int checkTableAndDeleteRecursive(Object obj1, SQLiteDatabase db,
HashMap<String, Integer> handleMap)
throws Exception {
EntityTable table = TableManager.getTable(obj1);
if (mTableManager.isSQLTableCreated(table.name)) {
return deleteRecursive(SQLBuilder.buildDeleteSql(obj1), obj1, db, handleMap);
}
return SQLStatement.NONE;
}
/**
* 处理一个实体中所有的关联实体。
*/
private void handleMapping(Object key1, Object obj1, SQLiteDatabase db,
boolean insertNew, HashMap<String, Integer> handleMap)
throws Exception {
EntityTable table1 = TableManager.getTable(obj1);
// 2. 存储[关联实体]以及其[关系映射]
if (table1.mappingList != null) {
for (MapProperty map : table1.mappingList) {
if (map.isToOne()) {
// handle <one to one>,<many to one> relation.
Object obj2 = FieldUtil.get(map.field, obj1);
EntityTable table2 = TableManager.getTable(map.field.getType());
handleMapToOne(table1, table2, key1, obj2, db, insertNew, handleMap);
} else if (map.isToMany()) {
// hanlde <one to many>,<many to many> relation.
Object array = FieldUtil.get(map.field, obj1);
if (ClassUtil.isCollection(map.field.getType())) {
EntityTable table2 = TableManager.getTable(FieldUtil.getGenericType(map.field));
handleMapToMany(table1, table2, key1, (Collection<?>) array, db, insertNew, handleMap);
} else if (ClassUtil.isArray(map.field.getType())) {
EntityTable table2 = TableManager.getTable(FieldUtil.getComponentType(map.field));
Collection<?> coll = null;
if (array != null) {
// 一定要强转为(Object[])
coll = Arrays.asList((Object[]) array);
}
handleMapToMany(table1, table2, key1, coll, db, insertNew, handleMap);
} else {
throw new RuntimeException("OneToMany and ManyToMany Relation, you must use collection or array object");
}
}
}
}
}
/**
* 处理N对1关系的关联实体
*/
private void handleMapToOne(EntityTable table1, EntityTable table2, Object key1, Object obj2,
SQLiteDatabase db, boolean insertNew, HashMap<String, Integer> handleMap)
throws Exception {
if (obj2 != null) {
// 注意:先递归处理关联对象(如果其主键无值,可以通过先处理赋值)
if (insertNew) {
// 递归存储[关联实体]
checkTableAndSaveRecursive(obj2, db, handleMap);
} else {
// 递归删除[关联实体]
checkTableAndDeleteRecursive(obj2, db, handleMap);
}
}
// 现在处理(当前实体)和(关联对象)的[映射关系]
String mapTableName = TableManager.getMapTableName(table1, table2);
// 删掉旧的[映射关系]
mTableManager.checkOrCreateMappingTable(db, mapTableName, table1.name, table2.name);
SQLStatement st = SQLBuilder.buildMappingDeleteSql(mapTableName, key1, table1);
st.execDelete(db);
// 存储新的[映射关系]
if (insertNew && obj2 != null) {
Object key2 = FieldUtil.get(table2.key.field, obj2);
st = SQLBuilder.buildMappingToOneSql(mapTableName, key1, key2, table1, table2);
if (st != null) {
st.execInsert(db);
}
}
}
/**
* 处理N对N关系的关联实体
*/
private void handleMapToMany(EntityTable table1, EntityTable table2, Object key1, Collection coll,
SQLiteDatabase db, boolean insertNew, HashMap<String, Integer> handleMap)
throws Exception {
//ArrayList<String> keyList = new ArrayList<String>();
//StringBuilder sqlForMap = new StringBuilder();
if (coll != null) {
//boolean isF = true;
//String key1Str = String.valueOf(key1);
//Class<?> class2 = null;
// 遍历每个关联的实体
for (Object obj2 : coll) {
if (obj2 != null) {
// 注意:先递归处理关联对象(如果其主键无值,可以通过先处理赋值)
if (insertNew) {
// 递归存储[关联实体]
checkTableAndSaveRecursive(obj2, db, handleMap);
} else {
// 递归删除[关联实体]
checkTableAndDeleteRecursive(obj2, db, handleMap);
}
//if (class2 == null) {
// class2 = obj2.getClass();
//}
// 提前构造[存储新映射关系]的SQL语句和参数
//if (insertNew) {
// Object key2 = FieldUtil.get(table2.key.field, obj2);
// if (key2 != null) {
// if (isF) {
// sqlForMap.append(SQLBuilder.TWO_HOLDER);
// isF = false;
// } else {
// sqlForMap.append(SQLBuilder.COMMA).append(SQLBuilder.TWO_HOLDER);
// }
// keyList.add(key1Str);
// keyList.add(String.valueOf(key2));
// }
//}
}
}
}
// 现在处理(当前实体)和(关联对象)的[映射关系]
String tableName = TableManager.getMapTableName(table1, table2);
// 删掉旧的[映射关系]
mTableManager.checkOrCreateMappingTable(db, tableName, table1.name, table2.name);
SQLStatement delSql = SQLBuilder.buildMappingDeleteSql(tableName, key1, table1);
delSql.execDelete(db);
// 存储新的[映射关系]
if (insertNew && !Checker.isEmpty(coll)) {
ArrayList<SQLStatement> sqlList = SQLBuilder.buildMappingToManySql(key1, table1, table2, coll);
if (!Checker.isEmpty(sqlList)) {
for(SQLStatement sql: sqlList){
sql.execInsert(db);
}
}
}
// 存储新的[映射关系]
//if (insertNew && !Checker.isEmpty(keyList)) {
// Object[] args = keyList.toArray(new String[keyList.size()]);
// SQLStatement addSql = new SQLStatement();
// addSql.sql = SQLBuilder.REPLACE + SQLBuilder.INTO + tableName
// + SQLBuilder.PARENTHESES_LEFT + table1.name + SQLBuilder.COMMA
// + table2.name + SQLBuilder.PARENTHESES_RIGHT + SQLBuilder.VALUES + sqlForMap;
// addSql.bindArgs = args;
// addSql.execInsert(db);
//}
}
}