Enregistrement d’objects étrangers nesteds avec ORMLite sur Android

Lorsque vous travaillez sur Android, ORMLite ne sauvegarde-t-il que des objects de niveau superficiel? J’ai une structure de données avec des objects nesteds, tous deux nouvellement créés, et j’aimerais pouvoir les enregistrer tous les deux avec un seul appel à dao.create ()

Par exemple, j’ai la classe parent suivante.

@DatabaseTable public class Parent { @DatabaseField(generatedId=true) public int id; @DatabaseField public Ssortingng name; @DatabaseField public Child child; } 

et la classe enfant suivante.

 @DatabaseTable public class Child { @DatabaseField(generatedId=true) public int id; @DatabaseField public Ssortingng name; } 

Je veux pouvoir faire ce qui suit.

 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); 

Dans ce cas, l’object parent est conservé mais l’object enfant et la colonne child_id générée child_id dans la table parent sont définis sur 0. Ce comportement est-il normal? Existe-t-il un moyen pour que les objects nesteds persistent et propagent la clé primaire?

Dans ce cas, l’object parent est conservé mais l’object enfant et la colonne child_id générée automatiquement dans la table parent sont définis sur 0. Ce comportement est-il normal?

OrmLite ne sauvegarde pas automatiquement les objects nesteds comme les autres ORM. Il est conçu en prenant la partie “Lite” de son nom au sérieux et avec la devise KISS en tête.

Cependant, vous pouvez facilement obtenir que les objects nesteds fonctionnent en créant l’enfant avant de créer le parent.

 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); 

Une autre chose à noter est que lorsque vous interrogez un object Parent, l’object enfant que vous récupérez n’a que son champ ID récupéré. Si l’ID est un int généré automatiquement (par exemple), le champ de nom ci-dessus ne sera pas extrait tant que vous n’avez pas effectué de mise à jour sur l’object enfant.

 // 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); 

Pour plus de documentation à ce sujet, consultez la page en ligne sur les champs d’object étranger .

Avez-vous essayé ceci?

 @DatabaseField(foreign = true, foreignAutoCreate = true, foreignAutoRefresh = true) public Child child; 

J’utilise ORMLite 4.35.

Comme mentionné, cela ne semble pas être pris en charge dans la version allégée. J’ai écrit une simple fonction récursive pour enregistrer tous les objects référencés. J’ai eu du mal à faire en sorte que les génériques jouent bien, alors je les ai tous supprimés. J’ai également créé une classe d’entité de base pour mes objects de firebase database.

Alors voici ce que j’ai écrit. Si quelqu’un peut obtenir le même code pour travailler avec des génériques appropriés, ou peut l’améliorer, n’hésitez pas à le modifier.

  // Debugging identity tag public static final Ssortingng TAG = DatabaseHelper.class.getName(); // Static map of common DAO objects @SuppressWarnings("rawtypes") private static final Map> sDaoClassMap = new HashMap>(); /** * 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.

* 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 atsortingbute 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); } } } } } // Resortingeve the common DAO for the entity class Dao dao = (Dao) 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; 

Quelques notes sur cette solution

  1. (foreignAutoCreate = true) ne fonctionne que si le champ ID n’est pas défini (null ou 0) conformément à la documentation ORMlite http://ormlite.com/javadoc/ormlite-core/com/j256/ormlite/field/DatabaseField.html

    • foreignAutoCreate: “Définissez cette valeur sur true (valeur par défaut false) pour que le champ étranger soit créé automatiquement à l’aide de son object DAO interne si le champ ID n’est pas défini (null ou 0).”
  2. Cela ne fonctionne que si generateId est également défini sur true pour la table enfant conformément à la documentation ORMlite .