Search in sources :

Example 1 with LazyForeignCollection

use of com.j256.ormlite.dao.LazyForeignCollection in project robospice by stephanenicolas.

the class InDatabaseObjectPersister method saveAllForeignObjectsToCache.

/**
 * During this operation, we must save a new POJO (parent) into the database. The problem is
 * that is the POJO contains children POJOs, then saving the parent would not work as the parent
 * must exist in the database prior to saving the children. SO :
 * <ul>
 * <li>we copy the children into memory,
 * <li>put the children to null on parent
 * <li>save the parent to the database
 * <li>if saving filled the parent with previous children, we remove them
 * <li>re inject the children into the parent
 * <li>save the children (as the parent now exists in database).
 * </ul>
 *
 * @param data the parent POJO to save in the database.
 * @throws SQLException
 * @throws IllegalArgumentException
 * @throws IllegalAccessException
 * @throws InvocationTargetException
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
protected <E> void saveAllForeignObjectsToCache(E data) throws SQLException, IllegalAccessException, InvocationTargetException {
    // copy children on memory
    // set children to null on parents so that we can save the parent
    // without cascade
    Map<Field, Collection<?>> mapFieldToCollection = new HashMap<Field, Collection<?>>();
    Class<? extends Object> parentClass = data.getClass();
    for (Field field : parentClass.getDeclaredFields()) {
        ForeignCollectionField annotation = field.getAnnotation(ForeignCollectionField.class);
        if (annotation != null) {
            Collection<?> collectionCopy = new ArrayList();
            Method getMethod = DatabaseFieldConfig.findGetMethod(field, true);
            Collection collectionInObject = (Collection<?>) getMethod.invoke(data);
            if (collectionInObject != null) {
                collectionCopy.addAll(collectionInObject);
            }
            Method setMethod = DatabaseFieldConfig.findSetMethod(field, true);
            setMethod.invoke(data, (Object) null);
            mapFieldToCollection.put(field, collectionCopy);
        }
    }
    // save parents without cascade
    databaseHelper.createOrUpdateInDatabase(data, (Class<E>) parentClass);
    // get the child from a previous database record
    databaseHelper.refreshFromDatabase(data, (Class<E>) parentClass);
    // collection field of the parent
    for (Field field : parentClass.getDeclaredFields()) {
        if (field.getAnnotation(ForeignCollectionField.class) != null) {
            Method getMethod = DatabaseFieldConfig.findGetMethod(field, true);
            Collection collectionInObject = (Collection<?>) getMethod.invoke(data);
            // lazy collection are not loaded from database, so we load them
            if (collectionInObject instanceof LazyForeignCollection) {
                ((LazyForeignCollection) collectionInObject).refreshCollection();
            }
            ParameterizedType listType = (ParameterizedType) field.getGenericType();
            Class<?> itemInListClass = (Class<?>) listType.getActualTypeArguments()[0];
            databaseHelper.deleteFromDataBase(collectionInObject, itemInListClass);
        }
    }
    // we now saved the parent and can fill the foreign key of the children
    for (Map.Entry<Field, Collection<?>> entry : mapFieldToCollection.entrySet()) {
        Collection<?> collection = entry.getValue();
        // re-set complete children to the parent
        ConnectionSource connectionSource = databaseHelper.getConnectionSource();
        for (Object object : collection) {
            DatabaseTableConfig childDatabaseTableConfig = DatabaseTableConfig.fromClass(connectionSource, object.getClass());
            for (FieldType childFieldType : childDatabaseTableConfig.getFieldTypes(null)) {
                if (parentClass.equals(childFieldType.getType()) && childFieldType.isForeign()) {
                    childFieldType.assignField(object, data, true, null);
                }
            }
            // save children recursively
            saveAllForeignObjectsToCache(object);
        }
    }
    // notify
    if (mapHandledClassesToNotificationUri != null && mapHandledClassesToNotificationUri.containsKey(parentClass)) {
        Uri notificationUri = mapHandledClassesToNotificationUri.get(parentClass);
        if (notificationUri != null) {
            getApplication().getContentResolver().notifyChange(notificationUri, null);
            Object id = getIdField(data.getClass()).extractJavaFieldValue(data);
            Uri itemNotificationUri = notificationUri.buildUpon().appendPath(id.toString()).build();
            getApplication().getContentResolver().notifyChange(itemNotificationUri, null);
        }
    }
// future hook
}
Also used : ForeignCollectionField(com.j256.ormlite.field.ForeignCollectionField) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) Uri(android.net.Uri) FieldType(com.j256.ormlite.field.FieldType) ParameterizedType(java.lang.reflect.ParameterizedType) ForeignCollectionField(com.j256.ormlite.field.ForeignCollectionField) Field(java.lang.reflect.Field) LazyForeignCollection(com.j256.ormlite.dao.LazyForeignCollection) ConnectionSource(com.j256.ormlite.support.ConnectionSource) Collection(java.util.Collection) LazyForeignCollection(com.j256.ormlite.dao.LazyForeignCollection) HashMap(java.util.HashMap) Map(java.util.Map) DatabaseTableConfig(com.j256.ormlite.table.DatabaseTableConfig)

Aggregations

Uri (android.net.Uri)1 LazyForeignCollection (com.j256.ormlite.dao.LazyForeignCollection)1 FieldType (com.j256.ormlite.field.FieldType)1 ForeignCollectionField (com.j256.ormlite.field.ForeignCollectionField)1 ConnectionSource (com.j256.ormlite.support.ConnectionSource)1 DatabaseTableConfig (com.j256.ormlite.table.DatabaseTableConfig)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 ParameterizedType (java.lang.reflect.ParameterizedType)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1