android - simple - ormlite c#
Guardar objetos extraños anidados con ORMLite en Android (4)
Al hacer esto, el objeto padre se conserva pero no el objeto secundario y la columna auto_id_child_id en la tabla primaria se establece en 0. ¿Es este comportamiento normal?
OrmLite no guarda automáticamente objetos anidados automágicamente como otros ORM. Está diseñado tomando en serio la parte "Lite" de su nombre y con el lema de KISS en mente.
Sin embargo, puede hacer que los objetos anidados funcionen fácilmente creando el elemento secundario antes de crear el elemento primario.
Parent parent = new Parent();
parent.name = "ParentName";
Child child = new Child();
child.name = "ChildName";
parent.child = child;
// this will update the id in child
childDao.create(child);
// this saves the parent with the id of the child
parentDao.create(parent);
Una cosa más a tener en cuenta es que cuando consulta un objeto Parent, el objeto secundario que obtiene solo recupera su campo id. Si el ID es un int generado automáticamente (por ejemplo), el campo de nombre anterior no se recuperará hasta que realice una actualización en el objeto secundario.
// assuming the id of the Parent is the name
Parent parent = parentDao.queryForId("ParentName");
System.out.println("Child id should be set: " + parent.child.id);
System.out.println("Child name should be null: " + parent.child.name);
// now we refresh the child object to load all of the fields
childDao.refresh(parent.child);
System.out.println("Child name should now be set: " + parent.child.name);
Para obtener más documentación sobre esto, consulte la página en línea sobre Campos de objetos extraños .
Al trabajar en Android, ¿ORMLite solo guarda objetos de nivel superficial? Tengo una estructura de datos con Objetos anidados, ambos recién creados, y me gustaría poder guardarlos con una sola llamada a dao.create ()
Por ejemplo, tengo la siguiente clase para padres.
@DatabaseTable
public class Parent {
@DatabaseField(generatedId=true)
public int id;
@DatabaseField
public String name;
@DatabaseField
public Child child;
}
y la siguiente clase de niños.
@DatabaseTable
public class Child {
@DatabaseField(generatedId=true)
public int id;
@DatabaseField
public String name;
}
Quiero ser capaz de hacer lo siguiente.
Parent parent = new Parent();
parent.name = "ParentName";
Child child = new Child();
child.name = "ChildName";
parent.child = child;
// .. get helper and create dao object...
dao.create(parent);
Al hacer esto, el objeto padre se conserva pero no el objeto secundario y la columna child_id
en la tabla primaria se establece en 0. ¿Es este comportamiento normal? ¿Hay alguna manera de mantener persistentes los objetos anidados y propagar la clave primaria?
¿Has intentado esto?
@DatabaseField(foreign = true, foreignAutoCreate = true, foreignAutoRefresh = true)
public Child child;
Estoy usando ORMLite 4.35.
Como se mencionó, esto no parece ser compatible con la versión lite. Escribí una función recursiva simple para guardar todos los objetos referenciados. Tuve problemas para que los genéricos funcionaran bien, así que al final simplemente los eliminé. También hice una clase base de Entidad para mis objetos db.
Así que aquí está lo que escribí. Si alguien puede obtener el mismo código para trabajar con genéricos adecuados, o puede mejorarlo, no dude en editarlo.
// Debugging identity tag
public static final String TAG = DatabaseHelper.class.getName();
// Static map of common DAO objects
@SuppressWarnings("rawtypes")
private static final Map<Class, Dao<?, Integer>> sDaoClassMap = new HashMap<Class, Dao<?,Integer>>();
/**
* Persist an entity to the underlying database.
*
* @param context
* @param entity
* @return boolean flag indicating success
*/
public static boolean create(Context context, Entity entity) {
// Get our database manager
DatabaseHelper databaseHelper = DatabaseHelper.getHelper(context);
try {
// Recursively save entity
create(databaseHelper, entity);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Object is not an instance of the declaring class", e);
return false;
} catch (IllegalAccessException e) {
Log.e(TAG, "Field is not accessible from the current context", e);
return false;
} catch (SQLException e) {
Log.e(TAG, "Unable to create object", e);
return false;
}
// Release database helper
DatabaseHelper.release();
// Return true on success
return true;
}
/**
* Persist an entity to the underlying database.<br><br>
* For each field that has a DatabaseField annotation with foreign set to true,
* and is an instance of Entity, recursive attempt to persist that entity as well.
*
* @param databaseHelper
* @param entity
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws SQLException
*/
@SuppressWarnings("unchecked")
public static void create(DatabaseHelper databaseHelper, Entity entity) throws IllegalArgumentException, IllegalAccessException, SQLException {
// Class type of entity used for reflection
@SuppressWarnings("rawtypes")
Class clazz = entity.getClass();
// Search declared fields and save child entities before saving parent.
for(Field field : clazz.getDeclaredFields()) {
// Inspect annotations
for(Annotation annotation : field.getDeclaredAnnotations()) {
// Only consider fields with the DatabaseField annotation
if(annotation instanceof DatabaseField) {
// Check for foreign attribute
DatabaseField databaseField = (DatabaseField)annotation;
if(databaseField.foreign()) {
// Check for instance of Entity
Object object = field.get(entity);
if(object instanceof Entity) {
// Recursive persist referenced entity
create(databaseHelper, (Entity)object);
}
}
}
}
}
// Retrieve the common DAO for the entity class
Dao<Entity, Integer> dao = (Dao<Entity, Integer>) sDaoClassMap.get(clazz);
// If the DAO does not exist, create it and add it to the static map
if(dao == null) {
dao = BaseDaoImpl.createDao(databaseHelper.getConnectionSource(), clazz);
sDaoClassMap.put(clazz, dao);
}
// Persist the entity to the database
dao.create(entity);
}
@DatabaseField(foreign = true,foreignAutoCreate = true,foreignAutoRefresh = true)
public Child child;
Algunas notas sobre esta solución
(foreignAutoCreate = true) funciona solo si el campo ID no está configurado (nulo o 0) según la documentación de ORMlite http://ormlite.com/javadoc/ormlite-core/com/j256/ormlite/field/DatabaseField.html
- foreignAutoCreate: "Configure esto para que sea verdadero (valor predeterminado falso) para que el campo foráneo se cree automágicamente usando su DAO interno si el campo ID no está establecido (nulo o 0)".
Esto solo funciona si generateId también se establece en true para la tabla secundaria según la documentación de ORMlite .