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