房间插入“一对多”关系

12

我想使用Android Room处理"一对多"关系。我可以使用@Relation[1]轻松获取相关实体。根据[2][3],Room没有原生支持@Relation插入。在[3][4]中,关系是手动创建的(将“一个”对象和相关的“多个”对象手动设置ID)。然而,我更喜欢使用自增PK作为ID(我通过其名称(String)访问“一个”对象)。

有没有"优雅的方式"插入具有自增PK的相关实体("一对多")?

链接

  1. https://developer.android.com/reference/android/arch/persistence/room/Relation
  2. Android Room: Insert relation entities using Room
  3. https://issuetracker.google.com/issues/62848977
  4. https://android.jlelse.eu/android-architecture-components-room-relationships-bf473510c14a
1个回答

11
我发现@Insert方法可以返回一个long,用于插入项的新rowId [1]。

如果@Insert方法只接收1个参数,则可以返回long,该参数是插入项的新rowId。如果参数是数组或集合,则应返回long []或List。

而SQLite文档[2]说:

如果表包含一个类型为INTEGER PRIMARY KEY的列,则该列成为ROWID的别名。您可以使用任何四个不同的名称访问ROWID,原始描述的三个名称或给定给INTEGER PRIMARY KEY列的名称。所有这些名称都是彼此的别名,并在任何上下文中同样有效。

因此,我们可以这样做:

1)CompanyEntity.java

@Entity(tableName = "companies", indices = @Index(value = "name", unique = true)) public class CompanyEntity {
    @PrimaryKey (autoGenerate = true)
    public int id;
    @NonNull
    @ColumnInfo(name = "name")
    private final String mCompanyName;

    public CompanyEntity(@NonNull String companyName) {
        mCompanyName = companyName;
    }

    @NonNull
    public String getCompanyName() {
        return mCompanyName;
    }
}

2)EmployeeEntity.java

@Entity(tableName = "employee_list",
        foreignKeys = @ForeignKey(
                entity = CompanyEntity.class,
                parentColumns = "id",
                childColumns = "company_id",
                onDelete = CASCADE),
        indices = @Index("company_id"))
public class EmployeeEntity {
    @PrimaryKey(autoGenerate = true)
    public int id;
    @ColumnInfo(name = "company_id")
    private long mCompanyId;
    @NonNull
    @ColumnInfo(name = "name")
    private final String mName;

    public EmployeeEntity(@NonNull String name) {
        mName = name;
    }

    @NonNull
    public String getName() {
        return mName;
    }

    public long getCompanyId() {
        return mCompanyId;
    }

    public void setCompanyId(long companyId) {
        mCompanyId = companyId;
    }
}

3) 员工Dao.java

@Dao
public abstract class EmployeeDao {

    @Query("SELECT * FROM companies")
    public abstract List<CompanyEntity> selectAllCompanies();

    @Transaction
    @Query("SELECT * FROM companies WHERE name LIKE :companyName")
    public abstract List<CompanyEmployees> getEmployeesByCompanyName(String companyName);

    @Transaction
    public void insert(CompanyEntity companyEntity, List<EmployeeEntity> employeeEntities) {

        // Save rowId of inserted CompanyEntity as companyId
        final long companyId = insert(companyEntity);

        // Set companyId for all related employeeEntities
        for (EmployeeEntity employeeEntity : employeeEntities) {
            employeeEntity.setCompanyId(companyId);
            insert(employeeEntity);
        }

    }

    // If the @Insert method receives only 1 parameter, it can return a long,
    // which is the new rowId for the inserted item.
    // https://developer.android.com/training/data-storage/room/accessing-data
    @Insert(onConflict = REPLACE)
    public abstract long insert(CompanyEntity company);

    @Insert
    public abstract void insert(EmployeeEntity employee);

}

看起来它运行得很好。

完整的源代码和示例项目: https://github.com/relativizt/android-room-one-to-many-auto-pk

链接

  1. https://developer.android.com/training/data-storage/room/accessing-data
  2. https://www.sqlite.org/autoinc.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接