在Android上使用ORMLite保存嵌套的外部对象

在Android上工作时,ORMLite只保存浅层对象吗? 我有一个嵌套的对象的数据结构,这两个都是新创build的,我希望能够通过一次调用dao.create()来保存它们。

例如,我有以下父类。

@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.这是正常的行为吗? 有没有办法让嵌套对象保持并传播主键?

当这样做的时候,父对象被持久化了,但是父对象的子对象和自动生成的child_id列都没有被设置为0.这是正常的行为吗?

OrmLite不像其他ORM那样自动保存嵌套对象。 它的devise严格遵循“精简”部分的名称,并以KISS格言为基础。

但是, 创build父项之前 ,可以通过创build子项来轻松获取嵌套对象。

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

还有一点要注意的是,当你查询一个Parent对象时,你得到的子对象只有它的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); 

有关这方面的更多文档,请参阅有关外来对象字段的在线页面。

你试过这个吗?

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

我正在使用ORMLite 4.35。

如前所述,这在lite版本中似乎不被支持。 我写了一个简单的recursion函数来保存所有引用的对象。 我有问题得到generics打好,所以最后我把他们都删除了。 我也为我的数据库对象做了一个基本的实体类。

所以这就是我写的。 如果任何人都可以得到相同的代码来使用适当的generics,或者可以改进它,请随时编辑。

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

有关此解决scheme的一些注释

  1. (foreignAutoCreate = true)只有在根据ORMlite文档没有设置ID字段(空或0)时才起作用http://ormlite.com/javadoc/ormlite-core/com/j256/ormlite/field/DatabaseField.html

    • foreignAutoCreate:“如果没有设置ID字段(空或0),则将其设置为true(默认为false),以便使用其内部DAO自动创build外部字段。
  2. 这仅适用于根据ORMlite文档中的childId也设置为true的子表。