Aks*_*iya 54 android android-room android-architecture-components
我在Room使用Relation添加了一对多的关系.我在这篇文章中提到了在Room中为关系编写以下代码.
该帖子告诉如何从数据库中读取值,但将实体存储到数据库中导致userId
为空,这意味着两个表之间没有关系.
我不知道什么是理想的途径,insert
一个User
并List of Pet
到数据库中,同时具有userId
价值.
1)用户实体:
@Entity
public class User {
@PrimaryKey
public int id; // User id
}
Run Code Online (Sandbox Code Playgroud)
2)宠物实体:
@Entity
public class Pet {
@PrimaryKey
public int id; // Pet id
public int userId; // User id
public String name;
}
Run Code Online (Sandbox Code Playgroud)
3)UserWithPets POJO:
// Note: No annotation required at this class definition.
public class UserWithPets {
@Embedded
public User user;
@Relation(parentColumn = "id", entityColumn = "userId", entity = Pet.class)
public List<Pet> pets;
}
Run Code Online (Sandbox Code Playgroud)
现在要从DB获取记录,我们使用以下内容DAO
:
@Dao
public interface UserDao {
@Insert
fun insertUser(user: User)
@Query("SELECT * FROM User")
public List<UserWithPets> loadUsersWithPets();
}
Run Code Online (Sandbox Code Playgroud)
编辑
我在问题跟踪器上创建了此问题https://issuetracker.google.com/issues/62848977.希望他们能为此做些什么.
Kie*_*all 30
您可以通过将Dao从接口更改为抽象类来完成此操作.
@Dao
public abstract class UserDao {
public void insertPetsForUser(User user, List<Pet> pets){
for(Pet pet : pets){
pet.setUserId(user.getId());
}
_insertAll(pets);
}
@Insert
abstract void _insertAll(List<Pet> pets); //this could go in a PetDao instead...
@Insert
public abstract void insertUser(User user);
@Query("SELECT * FROM User")
abstract List<UserWithPets> loadUsersWithPets();
}
Run Code Online (Sandbox Code Playgroud)
你也可以通过拥有一个User
对象来进一步发展@Ignored List<Pet> pets
@Entity
public class User {
@PrimaryKey
public int id; // User id
@Ignored
public List<Pet> pets
}
Run Code Online (Sandbox Code Playgroud)
然后道可以映射UserWithPets
到用户:
public List<User> getUsers() {
List<UserWithPets> usersWithPets = loadUserWithPets();
List<User> users = new ArrayList<User>(usersWithPets.size())
for(UserWithPets userWithPets: usersWithPets) {
userWithPets.user.pets = userWithPets.pets;
users.add(userWithPets.user);
}
return users;
}
Run Code Online (Sandbox Code Playgroud)
这将为您留下完整的Dao:
@Dao
public abstract class UserDao {
public void insertAll(List<User> users) {
for(User user:users) {
if(user.pets != null) {
insertPetsForUser(user, user.pets);
}
}
_insertAll(users);
}
private void insertPetsForUser(User user, List<Pet> pets){
for(Pet pet : pets){
pet.setUserId(user.getId());
}
_insertAll(pets);
}
public List<User> getUsersWithPetsEagerlyLoaded() {
List<UserWithPets> usersWithPets = _loadUsersWithPets();
List<User> users = new ArrayList<User>(usersWithPets.size())
for(UserWithPets userWithPets: usersWithPets) {
userWithPets.user.pets = userWithPets.pets;
users.add(userWithPets.user);
}
return users;
}
//package private methods so that wrapper methods are used, Room allows for this, but not private methods, hence the underscores to put people off using them :)
@Insert
abstract void _insertAll(List<Pet> pets);
@Insert
abstract void _insertAll(List<User> users);
@Query("SELECT * FROM User")
abstract List<UserWithPets> _loadUsersWithPets();
}
Run Code Online (Sandbox Code Playgroud)
你可能想要在PetDAO中使用insertAll(List<Pet>)
和insertPetsForUser(User, List<Pet>)
方法......你如何对你的DAO进行分区取决于你!:)
无论如何,这只是另一种选择.在DataSource对象中包装DAO也很有效.
Dip*_*rma 24
在Room Library中进行任何更新之前没有本机解决方案,但您可以通过技巧来完成此操作.找到下面提到的.
只需创建一个带宠物的用户(忽略宠物).
@Entity
public class User {
@PrimaryKey
public int id;
@Ignore
private List<Pet> petList;
}
Run Code Online (Sandbox Code Playgroud)创造宠物.
@Entity
public class Pet
{
@PrimaryKey
public int id;
public int userId;
public String name;
}
Run Code Online (Sandbox Code Playgroud)现在终于在UserDao了.
@Insert
public abstract void insertUser(User user);
@Insert
public abstract void insertPetList(List<Pet> pets);
@Query("SELECT * FROM User WHERE id =:id")
public abstract User getUser(int id);
@Query("SELECT * FROM Pet WHERE userId =:userId")
public abstract List<Pet> getPetList(int userId);
public void insertUserWithPet(User user) {
List<Pet> pets = user.getPetList();
for (int i = 0; i < pets.size(); i++) {
pets.get(i).setUserId(user.getId());
}
insertPetList(pets);
insertUser(user);
}
public User getUserWithPets(int id) {
User user = getUser(id);
List<Pet> pets = getPetList(id);
user.setPetList(pets);
return user;
}
Run Code Online (Sandbox Code Playgroud)您可以通过此方法解决问题,而无需创建UserWithPets POJO.
由于Room不管理实体的关系,您必须自己设置userId
每个宠物并保存它们.只要一次没有太多宠物,我会用一种insertAll
方法来保持它的简短.
@Dao
public interface PetDao {
@Insert
void insertAll(List<Pet> pets);
}
Run Code Online (Sandbox Code Playgroud)
我认为目前没有更好的方法.
为了使处理更容易,我在DAO上面的层中使用了一个抽象:
public void insertPetsForUser(User user, List<Pet> pets){
for(Pet pet : pets){
pet.setUserId(user.getId());
}
petDao.insertAll(pets);
}
Run Code Online (Sandbox Code Playgroud)
目前没有针对此问题的本地解决方案。我在 Google 的问题跟踪器上创建了这个https://issuetracker.google.com/issues/62848977,架构组件团队表示他们将在 Room 库 v1.0 中或之后添加本机解决方案。
临时解决方法:
同时您可以使用tknell提到的解决方案。
public void insertPetsForUser(User user, List<Pet> pets){
for(Pet pet : pets){
pet.setUserId(user.getId());
}
petDao.insertAll(pets);
}
Run Code Online (Sandbox Code Playgroud)
现在在 v2.1.0 Room 似乎不适合具有嵌套关系的模型。它需要大量的样板代码来维护它们。例如手动插入列表、创建和映射本地 ID。
这种关系映射操作是由 Requery https://github.com/requery/requery开箱即用完成的。此外,它没有插入枚举的问题,并且有一些用于其他复杂类型(如 URI)的转换器。
归档时间: |
|
查看次数: |
28245 次 |
最近记录: |