13

का उपयोग करके संबंध इकाइयों को सम्मिलित करें मैंने Relation का उपयोग करके कमरे में कई रिश्ते में एक जोड़ा है। मैंने कक्ष में संबंध के लिए निम्नलिखित कोड लिखने के लिए this post पर संदर्भित किया है।एंड्रॉइड रूम: कक्ष

पद बताता है कि कैसे डेटाबेस से मानों पढ़ लेकिन संस्थाओं के भंडारण में डेटाबेस userId के परिणामस्वरूप रिक्त जिसका अर्थ है वहाँ 2 तालिकाओं के बीच कोई संबंध नहीं है।

मुझे यकीन है कि क्या डेटाबेस में insert एक User और List of Pet करने के लिए आदर्श तरीका है, जबकि userId मूल्य होने नहीं हूँ।

1) उपयोगकर्ता निकाय:

@Entity 
public class User { 
    @PrimaryKey 
    public int id; // User id 
} 

2) पालतू पशु इकाई:

@Entity 
public class Pet { 
    @PrimaryKey 
    public int id;  // Pet id 
    public int userId; // User id 
    public String name; 
} 

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

अब डीबी से रिकॉर्ड उपयोग हम लाने के लिए निम्नलिखित DAO:

@Dao 
public interface UserDao { 
    @Insert 
    fun insertUser(user: User) 

    @Query("SELECT * FROM User") 
    public List<UserWithPets> loadUsersWithPets(); 
} 

संपादित

मैं इस मुद्दे पर नजर पर इस समस्या का https://issuetracker.google.com/issues/62848977 बनाया है। उम्मीद है कि वे इसके बारे में कुछ करेंगे।

उत्तर

5

चूंकि कक्ष इकाइयों के संबंधों का प्रबंधन नहीं करता है, तो आपको प्रत्येक पालतू जानवर पर userId सेट करना होगा और उन्हें सहेजना होगा। जब तक एक बार में बहुत से पालतू जानवर नहीं होते हैं, तब तक मैं इसे कम रखने के लिए insertAll विधि का उपयोग करता हूं।

@Dao 
public interface PetDao { 
    @Insert 
    void insertAll(List<Pet> pets); 
} 

मैं वहाँ इस समय किसी भी बेहतर तरीका है नहीं लगता।

आसान बनाने के लिए से निपटने, मैं एक अमूर्त परत में DAOs ऊपर का उपयोग करेंगे:

public void insertPetsForUser(User user, List<Pet> pets){ 

    for(Pet pet : pets){ 
     pet.setUserId(user.getId()); 
    } 

    petDao.insertAll(pets); 
} 
+0

मैंने 'स्ट्रीम' का उपयोग करके इसका प्रयास किया। मुझे उम्मीद है कि ऐसा करने का एक बेहतर तरीका है। –

+0

मुझे नहीं लगता कि एक बेहतर तरीका है, क्योंकि प्रलेखन कहता है कि उन्होंने जानबूझकर पुस्तकालय से संदर्भ छोड़े हैं: https://developer.android.com/topic/libraries/architecture/room.html#no-object- संदर्भ – tknell

+0

मैंने इस समस्या को समस्या ट्रैकर पर https://issuetracker.google.com/issues/62848977 बनाया है। उम्मीद है कि वे इसके बारे में कुछ करेंगे। –

1

इस समय वहाँ है कोई मूल समाधान इस समस्या का। मैंने Google के अंक ट्रैकर पर यह https://issuetracker.google.com/issues/62848977 बनाया है और आर्किटेक्चर कंपोनेंट्स टीम ने कहा है कि वे कक्ष पुस्तकालय के v1.0 में या उसके बाद मूल समाधान जोड़ देंगे।

अस्थायी समाधान:

इस बीच आप समाधान tknell ने उल्लेख उपयोग कर सकते हैं।

public void insertPetsForUser(User user, List<Pet> pets){ 

    for(Pet pet : pets){ 
     pet.setUserId(user.getId()); 
    } 

    petDao.insertAll(pets); 
} 
9

आप अपने दाओ को एक इंटरफेस से एक अमूर्त वर्ग में बदलकर ऐसा कर सकते हैं।

@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(); 
} 

तुम भी एक User वस्तु होने से आगे जा सकते हैं एक @Ignored List<Pet> pets

@Entity 
public class User { 
    @PrimaryKey 
    public int id; // User id 

    @Ignored 
    public List<Pet> pets 
} 

और फिर दाव उपयोगकर्ता को 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; 
} 

यह पूर्ण के साथ छोड़ देता है दाओ:

@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(); 
} 

आप एक PetDAO बजाय में insertAll(List<Pet>) और insertPetsForUser(User, List<Pet>) तरीकों के लिए चाहते हो सकता है ... कैसे आप अपने DAOs विभाजन आप पर निर्भर है! :)

वैसे भी, यह एक और विकल्प है। डेटासोर्स ऑब्जेक्ट्स में अपने डीएओ को लपेटना भी काम करता है।

+0

इंटरफ़ेस की बजाय अमूर्त कक्षा में सुविधा विधि को रखने का शानदार विचार। –

2

कक्ष पुस्तकालय में किसी भी अद्यतन तक कोई मूल समाधान नहीं है लेकिन आप इसे एक चाल से कर सकते हैं। नीचे उल्लिखित खोजें।

  1. बस पालतू जानवरों के साथ उपयोगकर्ता बनाएं (पालतू जानवरों को अनदेखा करें)।

    @Entity 
    public class User { 
         @PrimaryKey 
         public int id; 
    
         @Ignore 
         private List<Pet> petList; 
    } 
    
  2. पालतू बनाएं।

    @Entity 
    public class Pet 
    { 
        @PrimaryKey 
        public int id;  
        public int userId; 
        public String name; 
    } 
    
  3. अब अंत में उपयोगकर्ताडाओ में।

    @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; 
    } 
    

आपका समस्या UserWithPets POJO बनाने के बिना इस से हल किया जा सकता है।

+0

मुझे यह पसंद है, क्योंकि यह UserWithPets POJO से बचाता है। डिफ़ॉल्ट तरीकों का उपयोग करके डीएओ एक इंटरफ़ेस भी हो सकता है। केवल नकारात्मकता यह है कि insertUser() और insertPetList() सार्वजनिक विधियां हैं, लेकिन किसी क्लाइंट द्वारा उपयोग नहीं किया जाना चाहिए। मैंने इन विधियों के नाम से पहले एक अंडरस्कोर डाला है ताकि यह दिखाया जा सके कि उन्हें ऊपर दिखाए गए अनुसार उपयोग नहीं किया जाना चाहिए। – guglhupf

संबंधित मुद्दे