Skip to content

Commit

Permalink
Handling query associated model when foreign keys are not in the curr…
Browse files Browse the repository at this point in the history
…ent model's table.
  • Loading branch information
sinyu890807 committed May 8, 2014
1 parent fc9524f commit c1974ef
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 78 deletions.
140 changes: 70 additions & 70 deletions src/org/litepal/crud/DataHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,76 @@ protected Object[] getConstructorParams(Constructor<?> constructor) {
}
return params;
}

/**
* Get value from database by cursor, then set the value into modelInstance.
*
* @param modelInstance
* The model to set into.
* @param supportedFields
* Corresponding to each column in database.
* @param foreignKeyAssociations
* Associated classes which have foreign keys in the current
* model's table.
* @param cursor
* Use to get value from database.
* @throws SecurityException
* @throws IllegalArgumentException
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
protected void setValueToModel(Object modelInstance, List<Field> supportedFields,
List<AssociationsInfo> foreignKeyAssociations, Cursor cursor) throws SecurityException,
IllegalArgumentException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException {
for (Field field : supportedFields) {
String getMethodName = genGetColumnMethod(field);
String columnName = isIdColumn(field.getName()) ? "id" : field.getName();
int columnIndex = cursor.getColumnIndex(BaseUtility.changeCase(columnName));
if (columnIndex != -1) {
Class<?> cursorClass = cursor.getClass();
Method method = cursorClass.getMethod(getMethodName, int.class);
Object value = method.invoke(cursor, columnIndex);
if (isIdColumn(field.getName())) {
DynamicExecutor.setField(modelInstance, field.getName(), value,
modelInstance.getClass());
} else {
if (field.getType() == boolean.class || field.getType() == Boolean.class) {
if ("0".equals(String.valueOf(value))) {
value = false;
} else if ("1".equals(String.valueOf(value))) {
value = true;
}
} else if (field.getType() == char.class || field.getType() == Character.class) {
value = ((String) value).charAt(0);
}
putSetMethodValueByField((DataSupport) modelInstance, field, value);
}
}
}
if (foreignKeyAssociations != null) {
for (AssociationsInfo associationInfo : foreignKeyAssociations) {
String foreignKeyColumn = getForeignKeyColumnName(DBUtility
.getTableNameByClassName(associationInfo.getAssociatedClassName()));
int columnIndex = cursor.getColumnIndex(foreignKeyColumn);
if (columnIndex != -1) {
long associatedClassId = cursor.getLong(columnIndex);
try {
DataSupport associatedObj = (DataSupport) DataSupport.find(
Class.forName(associationInfo.getAssociatedClassName()),
associatedClassId);
if (associatedObj != null) {
putSetMethodValueByField((DataSupport) modelInstance,
associationInfo.getAssociateOtherModelFromSelf(), associatedObj);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}

/**
* Get the types of parameters for {@link ContentValues#put}. Need two
Expand Down Expand Up @@ -832,74 +902,4 @@ private String[] getCustomizedColumns(String[] columns,
return null;
}

/**
* Get value from database by cursor, then set the value into modelInstance.
*
* @param modelInstance
* The model to set into.
* @param supportedFields
* Corresponding to each column in database.
* @param foreignKeyAssociations
* Associated classes which have foreign keys in the current
* model's table.
* @param cursor
* Use to get value from database.
* @throws SecurityException
* @throws IllegalArgumentException
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private void setValueToModel(Object modelInstance, List<Field> supportedFields,
List<AssociationsInfo> foreignKeyAssociations, Cursor cursor) throws SecurityException,
IllegalArgumentException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException {
for (Field field : supportedFields) {
String getMethodName = genGetColumnMethod(field);
String columnName = isIdColumn(field.getName()) ? "id" : field.getName();
int columnIndex = cursor.getColumnIndex(BaseUtility.changeCase(columnName));
if (columnIndex != -1) {
Class<?> cursorClass = cursor.getClass();
Method method = cursorClass.getMethod(getMethodName, int.class);
Object value = method.invoke(cursor, columnIndex);
if (isIdColumn(field.getName())) {
DynamicExecutor.setField(modelInstance, field.getName(), value,
modelInstance.getClass());
} else {
if (field.getType() == boolean.class || field.getType() == Boolean.class) {
if ("0".equals(String.valueOf(value))) {
value = false;
} else if ("1".equals(String.valueOf(value))) {
value = true;
}
} else if (field.getType() == char.class || field.getType() == Character.class) {
value = ((String) value).charAt(0);
}
putSetMethodValueByField((DataSupport) modelInstance, field, value);
}
}
}
if (foreignKeyAssociations != null) {
for (AssociationsInfo associationInfo : foreignKeyAssociations) {
String foreignKeyColumn = getForeignKeyColumnName(DBUtility
.getTableNameByClassName(associationInfo.getAssociatedClassName()));
int columnIndex = cursor.getColumnIndex(foreignKeyColumn);
if (columnIndex != -1) {
long associatedClassId = cursor.getLong(columnIndex);
try {
DataSupport associatedObj = (DataSupport) DataSupport.find(
Class.forName(associationInfo.getAssociatedClassName()),
associatedClassId);
if (associatedObj != null) {
putSetMethodValueByField((DataSupport) modelInstance,
associationInfo.getAssociateOtherModelFromSelf(), associatedObj);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}

}
55 changes: 47 additions & 8 deletions src/org/litepal/crud/QueryHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.litepal.crud;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
Expand All @@ -10,6 +12,7 @@
import org.litepal.util.Const;
import org.litepal.util.DBUtility;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

Expand Down Expand Up @@ -43,10 +46,11 @@ class QueryHandler extends DataHandler {
* Which record to query.
* @return An object with founded data from database, or null.
*/
@SuppressWarnings("unchecked")
<T> T onFind(Class<T> modelClass, long id, boolean isEager) {
if (!isEager) {
List<T> dataList = query(modelClass, null, "id = ?", new String[] { String.valueOf(id) }, null,
null, null, null, null);
List<T> dataList = query(modelClass, null, "id = ?",
new String[] { String.valueOf(id) }, null, null, null, null, null);
if (dataList.size() > 0) {
return dataList.get(0);
}
Expand All @@ -69,8 +73,9 @@ <T> T onFind(Class<T> modelClass, long id, boolean isEager) {
}
}
Log.d("TAG", fkInCurrentModel.toString());
List<T> dataList = query(modelClass, null, "id = ?", new String[] { String.valueOf(id) },
null, null, null, null, fkInCurrentModel);
List<T> dataList = query(modelClass, null, "id = ?",
new String[] { String.valueOf(id) }, null, null, null, null,
fkInCurrentModel);
DataSupport baseObj = null;
if (dataList.size() > 0) {
baseObj = (DataSupport) dataList.get(0);
Expand All @@ -79,9 +84,8 @@ <T> T onFind(Class<T> modelClass, long id, boolean isEager) {
for (AssociationsInfo info : fkInOtherModel) {
String foreignKeyColumn = getForeignKeyColumnName(DBUtility
.getTableNameByClassName(info.getSelfClassName()));
// List<T> list = (List<T>) DataSupport.where("? = ?", foreignKeyColumn,
// String.valueOf(baseObj.getBaseObjId())).find(
// Class.forName(info.getAssociatedClassName()));
setAssociatedModel(baseObj, info.getAssociatedClassName(),
foreignKeyColumn, info);
}
}
return (T) baseObj;
Expand Down Expand Up @@ -139,7 +143,8 @@ <T> List<T> onFindAll(Class<T> modelClass, long... ids) {
if (isAffectAllLines(ids)) {
dataList = query(modelClass, null, null, null, null, null, "id", null, null);
} else {
dataList = query(modelClass, null, getWhereOfIdsWithOr(ids), null, null, null, "id", null, null);
dataList = query(modelClass, null, getWhereOfIdsWithOr(ids), null, null, null, "id",
null, null);
}
return dataList;
}
Expand Down Expand Up @@ -176,4 +181,38 @@ <T> List<T> onFind(Class<T> modelClass, String[] columns, String[] conditions, S
return null;
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private void setAssociatedModel(DataSupport baseObj, String className, String foreignKeyColumn,
AssociationsInfo info) {
Cursor cursor = null;
try {
List<Field> supportedFields = getSupportedFields(className);
String tableName = DBUtility.getTableNameByClassName(className);
cursor = mDatabase
.query(tableName, null, foreignKeyColumn + "=?",
new String[] { String.valueOf(baseObj.getBaseObjId()) }, null, null,
null, null);
if (cursor.moveToFirst()) {
do {
Constructor<?> constructor = findBestSuitConstructor(Class.forName(className));
DataSupport modelInstance = (DataSupport) constructor
.newInstance(getConstructorParams(constructor));
giveBaseObjIdValue(modelInstance,
cursor.getLong(cursor.getColumnIndexOrThrow("id")));
setValueToModel(modelInstance, supportedFields, null, cursor);
Collection collection = (Collection) takeGetMethodValueByField(baseObj,
info.getAssociateOtherModelFromSelf());
collection.add(modelInstance);
Log.d("TAG", "associated model is " + modelInstance);
} while (cursor.moveToNext());
}
} catch (Exception e) {
throw new DataSupportException(e.getMessage());
} finally {
if (cursor != null) {
cursor.close();
}
}
}

}

0 comments on commit c1974ef

Please sign in to comment.