40

Android で作業する場合、ORMLite は浅いレベルのオブジェクトのみを保存しますか? どちらも新しく作成されたネストされたオブジェクトを含むデータ構造があり、dao.create() への 1 回の呼び出しで両方を保存できるようにしたいと考えています。

たとえば、次の親クラスがあります。

@DatabaseTable
public class Parent {

  @DatabaseField(generatedId=true)
  public int id;

  @DatabaseField
  public String name;

  @DatabaseField
  public Child child;
}

および次の子クラス。

@DatabaseTable
public class Child {

  @DatabaseField(generatedId=true)
  public int id;

  @DatabaseField
  public String name;
}

以下ができるようになりたいです。

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

これを行うと、親オブジェクトは永続化されますが、子オブジェクトは永続化されずchild_id、親テーブルの自動生成された列は 0 に設定されます。これは正常な動作ですか? ネストされたオブジェクトを永続化し、主キーを伝播する方法はありますか?

4

4 に答える 4

47

これを試しましたか?

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

ORMLite 4.35 を使用しています。

于 2012-03-16T20:32:02.110 に答える
43

バージョン 4.27 の時点で、 ORMliteはフィールドの注釈でforeignAutoCreateおよびforeignAutoRefresh設定をサポートしています。@DatabaseField

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

これは、childフィールドを割り当てることを意味しid、親の作成時に子のフィールドが設定されていない場合は作成されます。foreignAutoRefresh親が取得されると、別の SQL 呼び出しが行われてフィールドにデータが入力されることを意味しますchild

これを行うと、親オブジェクトは永続化されますが、子オブジェクトは永続化されず、親テーブルの自動生成された child_id 列が 0 に設定されます。これは正常な動作ですか?

親を作成する前に子を作成することで、ORMLite が子オブジェクトを呼び出すタイミングをより詳細に制御することもできます。

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

もう 1 つ注意すべき点はforeignAutoRefresh = true、親オブジェクトのクエリを実行しないと、返される子オブジェクトのid フィールドのみが取得されるということです。id が自動生成された int の場合 (たとえば)、子オブジェクトを更新するまで、上記の名前フィールドは取得されません。

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

これに関する詳細なドキュメントについては、外部オブジェクト フィールドに関するオンライン ページを参照してください。

于 2011-01-20T14:39:30.967 に答える
4

前述のとおり、これはライト バージョンではサポートされていないようです。参照されるすべてのオブジェクトを保存する単純な再帰関数を作成しました。ジェネリックをうまくプレイさせるのに問題があったので、最終的にそれらをすべて削除しました。また、db オブジェクトの基本エンティティ クラスも作成しました。

だからここに私が書いたものがあります。誰かが同じコードを適切なジェネリックで動作させることができるか、それを改善できる場合は、自由に編集してください。

    // 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);
    }
于 2011-01-21T03:26:07.057 に答える