כשמשתמשים בספריית הקבועות של החדרים כדי לאחסן את נתוני האפליקציה, אפשר ליצור אינטראקציה בנתונים המאוחסנים באמצעות הגדרה של אובייקטים של גישה לנתונים או DAOs. כל DAO כוללת שיטות שמציעות גישה מופשטת למסד הנתונים של האפליקציה. בזמן הידור זמן, חדר יוצר באופן אוטומטי הטמעות של הפעלות הקמפיין (DAO) שהגדרתם.
באמצעות DAOs כדי לגשת למסד הנתונים של האפליקציה במקום בכלי ליצירת שאילתות או ישירות אפשר לשמור את ההפרדה של ארכיטקטורה מהותית את העיקרון. עם DAOs קל יותר לדמות גישה למסד נתונים לבדוק את האפליקציה.
המבנה של DAO
תוכלו להגדיר כל DAO כממשק או כמחלקה מופשטת. בסיסית
בדרך כלל משתמשים בממשק. בכל מקרה, עליך תמיד
מוסיפים הערות ל-DAO באמצעות @Dao. DAOs
אין נכסים, אבל הם מגדירים שיטה אחת או יותר לאינטראקציה
בנתונים במסד הנתונים של האפליקציה.
הקוד הבא הוא דוגמה ל-DAO פשוט שמגדיר שיטות (methods)
הוספה, מחיקה ובחירה של אובייקטים מסוג User במסד הנתונים של Room:
Kotlin
@Dao interface UserDao { @Insert fun insertAll(vararg users: User) @Delete fun delete(user: User) @Query("SELECT * FROM user") fun getAll(): List<User> }
Java
@Dao public interface UserDao { @Insert void insertAll(User... users); @Delete void delete(User user); @Query("SELECT * FROM user") List<User> getAll(); }
יש שני סוגים של שיטות DAO שמגדירות אינטראקציות עם מסדי נתונים:
- שיטות נוחות שמאפשרות להוסיף, לעדכן ולמחוק שורות בלי לכתוב קוד SQL.
- שיטות שאילתות שמאפשרות לכם לכתוב שאילתת SQL משלכם כדי לקיים אינטראקציה עם מסד נתונים.
בקטעים הבאים נדגים איך להשתמש בשני הסוגים של שיטות DAO כדי להגדיר את האינטראקציות במסד הנתונים שהאפליקציה שלך צריכה.
שיטות נוחות
החדר מספק הערות נוחות להגדרת שיטות שמניבות ביצועים פשוטים הכנסות, עדכונים ומחיקות בלי שתצטרכו לכתוב הצהרת SQL.
אם אתם צריכים להגדיר הוספה, עדכונים או מחיקות מורכבים יותר, או במקרה הצורך כדי להריץ שאילתה על הנתונים במסד הנתונים, צריך להשתמש בשיטת שאילתה.
הוספה
ההערה @Insert מאפשרת
להגדיר שיטות שמכניסות את הפרמטרים שלהן לטבלה המתאימה
מסד נתונים. הקוד הבא מציג דוגמאות לשיטות @Insert חוקיות
מוסיפים למסד הנתונים אובייקט אחד או יותר מסוג User:
Kotlin
@Dao interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertUsers(vararg users: User) @Insert fun insertBothUsers(user1: User, user2: User) @Insert fun insertUsersAndFriends(user: User, friends: List<User>) }
Java
@Dao public interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) public void insertUsers(User... users); @Insert public void insertBothUsers(User user1, User user2); @Insert public void insertUsersAndFriends(User user, List<User> friends); }
כל פרמטר ב-method @Insert חייב להיות מופע של חדר
סיווג ישות נתונים עם הערות
@Entity או אוסף של מופעי סיווג של ישות נתונים, שכל אחד מהם
מצביע למסד נתונים. כשמתבצעת קריאה ל-method @Insert, כל אחד מהחדר מתווסף
מופע של ישות שהועברה לטבלה המתאימה של מסד הנתונים.
אם ה-method @Insert מקבלת פרמטר יחיד, היא יכולה להחזיר long
, שהוא הערך rowId החדש של הפריט שהוכנס. אם הפרמטר
מערך או אוסף, ואז מחזירים מערך או אוסף
של long ערכים במקום זאת, כאשר כל ערך הוא rowId של אחד מהערכים
פריטים. למידע נוסף על החזרת ערכי rowId, יש לעיין בחומר העזר
תיעוד של @Insert
הערה והתיעוד של SQLite ל-Rowid
טבלאות.
עדכון
ההערה @Update מאפשרת
להגדיר שיטות שמעדכנות שורות מסוימות בטבלה של מסד נתונים. מוצא חן בעיניי
@Insert methods, methods של @Update מקבלות מופעים של ישויות נתונים כפרמטרים.
הקוד הבא מציג דוגמה ל-method @Update שמנסה
מעדכנים אובייקט User אחד או יותר במסד הנתונים:
Kotlin
@Dao interface UserDao { @Update fun updateUsers(vararg users: User) }
Java
@Dao public interface UserDao { @Update public void updateUsers(User... users); }
החדר הוא הראשי מפתח כדי להתאים עבר מופעים של ישויות לשורות במסד הנתונים. אם אין שורה עם אותה הגדרה המפתח הראשי, החדר לא מבצע שינויים.
שיטת @Update יכולה להחזיר ערך int שמציין את המספר
מתוך השורות שעודכנו בהצלחה.
מחיקה
ההערה @Delete מאפשרת
להגדיר שיטות למחיקת שורות ספציפיות מטבלה של מסד נתונים. מוצא חן בעיניי
@Insert methods, methods של @Delete מקבלות מופעים של ישויות נתונים כפרמטרים.
הקוד הבא מציג דוגמה ל-method @Delete שמנסה
מוחקים אובייקט User אחד או יותר ממסד הנתונים:
Kotlin
@Dao interface UserDao { @Delete fun deleteUsers(vararg users: User) }
Java
@Dao public interface UserDao { @Delete public void deleteUsers(User... users); }
החדר הוא הראשי מפתח כדי להתאים עבר מופעים של ישויות לשורות במסד הנתונים. אם אין שורה עם אותה התווית המפתח הראשי, החדר לא מבצע שינויים.
השיטה @Delete יכולה להחזיר ערך int שמציין את מספר
שורות שנמחקו בהצלחה.
שיטות השאילתה
ההערה @Query מאפשרת
לכתוב הצהרות SQL ולחשוף אותן כשיטות DAO. שימוש בשיטות השאילתה האלה כדי
ממסד הנתונים של האפליקציה או כשצריך לבצע פעולות מורכבות יותר
הוספה, עדכונים ומחיקות.
חדר מאמת שאילתות SQL בזמן הקומפילציה. המשמעות היא שאם יש בעיה בשאילתה שלך, תתקבל שגיאת הידור (compilation) במקום כשל בסביבת זמן הריצה.
שאילתות פשוטות
הקוד הבא מגדיר שיטה שמשתמשת בשאילתת SELECT פשוטה כדי להחזיר
כל האובייקטים User במסד הנתונים:
Kotlin
@Query("SELECT * FROM user") fun loadAllUsers(): Array<User>
Java
@Query("SELECT * FROM user") public User[] loadAllUsers();
בקטעים הבאים מוסבר איך לשנות את הדוגמה הזו לשימוש רגיל במקרים שונים.
החזרת קבוצת משנה של עמודות טבלה
ברוב המקרים צריך להחזיר רק קבוצת משנה של העמודות מהטבלה אתם שואלים את השאלות. לדוגמה, ייתכן שממשק המשתמש יציג רק את את שם המשפחה של המשתמש במקום את כל הפרטים על המשתמש. כדי לשמור ומפשטים את הרצת השאילתה, השדות שנחוצים לכם.
בעזרת Room אפשר להחזיר אובייקט פשוט מכל אחת מהשאילתות כל עוד אפשר למפות את קבוצת עמודות התוצאות לאובייקט שמוחזר. לדוגמה, יכול להגדיר את האובייקט הבא כך שיכלול את השם הפרטי ושם המשפחה של המשתמש:
Kotlin
data class NameTuple( @ColumnInfo(name = "first_name") val firstName: String?, @ColumnInfo(name = "last_name") val lastName: String? )
Java
public class NameTuple { @ColumnInfo(name = "first_name") public String firstName; @ColumnInfo(name = "last_name") @NonNull public String lastName; }
לאחר מכן אפשר להחזיר אובייקט פשוט משיטת השאילתה:
Kotlin
@Query("SELECT first_name, last_name FROM user") fun loadFullName(): List<NameTuple>
Java
@Query("SELECT first_name, last_name FROM user") public List<NameTuple> loadFullName();
החדר מבין שהשאילתה מחזירה ערכים של first_name ושל
last_name עמודות, ושאפשר למפות את הערכים האלה לשדות
כיתה אחת (NameTuple). אם השאילתה מחזירה עמודה שלא ממופה לשדה מסוים.
באובייקט שהמוחזר, מופיעה אזהרה בחדר.
העברת פרמטרים פשוטים לשאילתה
ברוב המקרים, שיטות ה-DAO צריכות לקבל פרמטרים כדי לבצע פעולות סינון. החדר תומך בשימוש בפרמטרים של שיטות כקישור. של שאילתות.
לדוגמה, הקוד הבא מגדיר שיטה שמחזירה את כל המשתמשים. מעל גיל מסוים:
Kotlin
@Query("SELECT * FROM user WHERE age > :minAge") fun loadAllUsersOlderThan(minAge: Int): Array<User>
Java
@Query("SELECT * FROM user WHERE age > :minAge") public User[] loadAllUsersOlderThan(int minAge);
אפשר גם להעביר מספר פרמטרים או להפנות לאותו פרמטר בשאילתה, כפי שמוצג בקוד הבא:
Kotlin
@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge") fun loadAllUsersBetweenAges(minAge: Int, maxAge: Int): Array<User> @Query("SELECT * FROM user WHERE first_name LIKE :search " + "OR last_name LIKE :search") fun findUserWithName(search: String): List<User>
Java
@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge") public User[] loadAllUsersBetweenAges(int minAge, int maxAge); @Query("SELECT * FROM user WHERE first_name LIKE :search " + "OR last_name LIKE :search") public List<User> findUserWithName(String search);
העברת אוסף של פרמטרים לשאילתה
חלק משיטות DAO שלכם עשויות לדרוש מכם להעביר מספר משתנה של שלא ידועים עד זמן הריצה. החדר מבין שהפרמטר מייצג אוסף ומרחיב אותו באופן אוטומטי בזמן הריצה מספר הפרמטרים שסופקו.
לדוגמה, הקוד הבא מגדיר שיטה שמחזירה מידע על כל המשתמשים מתת-אזורים של אזורים:
Kotlin
@Query("SELECT * FROM user WHERE region IN (:regions)") fun loadUsersFromRegions(regions: List<String>): List<User>
Java
@Query("SELECT * FROM user WHERE region IN (:regions)") public List<User> loadUsersFromRegions(List<String> regions);
שליחת שאילתה לגבי כמה טבלאות
יכול להיות שבחלק מהשאילתות נדרשת גישה לכמה טבלאות כדי לחשב
תוצאה אחת. אפשר להשתמש בתנאי JOIN בשאילתות SQL כדי להפנות ליותר מ-
טבלה אחת.
הקוד הבא מגדיר שיטה שמאחדת שלוש טבלאות יחד כדי להחזיר הספרים שמושאלים כרגע למשתמש מסוים:
Kotlin
@Query( "SELECT * FROM book " + "INNER JOIN loan ON loan.book_id = book.id " + "INNER JOIN user ON user.id = loan.user_id " + "WHERE user.name LIKE :userName" ) fun findBooksBorrowedByNameSync(userName: String): List<Book>
Java
@Query("SELECT * FROM book " + "INNER JOIN loan ON loan.book_id = book.id " + "INNER JOIN user ON user.id = loan.user_id " + "WHERE user.name LIKE :userName") public List<Book> findBooksBorrowedByNameSync(String userName);
אפשר גם להגדיר אובייקטים פשוטים כדי להחזיר קבוצת משנה של עמודות מכמה עמודות. טבלאות משולבות, כמו שמתואר במאמר החזרת קבוצת משנה של טבלאות עמודות החשבון. הקוד הבא מגדיר DAO באמצעות שיטה מחזירה את שמות המשתמשים ואת שמות הספרים שהם שאלה:
Kotlin
interface UserBookDao { @Query( "SELECT user.name AS userName, book.name AS bookName " + "FROM user, book " + "WHERE user.id = book.user_id" ) fun loadUserAndBookNames(): LiveData<List<UserBook>> // You can also define this class in a separate file. data class UserBook(val userName: String?, val bookName: String?) }
Java
@Dao public interface UserBookDao { @Query("SELECT user.name AS userName, book.name AS bookName " + "FROM user, book " + "WHERE user.id = book.user_id") public LiveData<List<UserBook>> loadUserAndBookNames(); // You can also define this class in a separate file, as long as you add the // "public" access modifier. static class UserBook { public String userName; public String bookName; } }
החזרת מיפוי מרובה
בחדר 2.4 ואילך, אתם יכולים גם להריץ שאילתות על עמודות מכמה טבלאות ללא הגדרה של סיווג נתונים נוסף על ידי כתיבת שיטות שאילתה שמחזירות סוג נתונים multimap.
קחו לדוגמה את הדוגמה שבקטע הרצת שאילתות על מספר טבלאות.
במקום להחזיר רשימת מופעים של קטגוריית נתונים מותאמת אישית שמכילה
צמדים של User ו-Book מופעים, אפשר להחזיר מיפוי של User
Book ישירות משיטת השאילתה:
Kotlin
@Query( "SELECT * FROM user" + "JOIN book ON user.id = book.user_id" ) fun loadUserAndBookNames(): Map<User, List<Book>>
Java
@Query( "SELECT * FROM user" + "JOIN book ON user.id = book.user_id" ) public Map<User, List<Book>> loadUserAndBookNames();
אם שיטת השאילתה מחזירה מיפוי מרובה, אפשר לכתוב שאילתות שמשתמשות ב-
GROUP BY תנאים, כך שתוכלו לנצל את היכולות של SQL
חישובים וסינון מתקדמים. לדוגמה, אפשר לשנות את
שיטה loadUserAndBookNames() להחזרת משתמשים עם שלושה ספרים או יותר
עשה צ'ק-אאוט:
Kotlin
@Query( "SELECT * FROM user" + "JOIN book ON user.id = book.user_id" + "GROUP BY user.name WHERE COUNT(book.id) >= 3" ) fun loadUserAndBookNames(): Map<User, List<Book>>
Java
@Query( "SELECT * FROM user" + "JOIN book ON user.id = book.user_id" + "GROUP BY user.name WHERE COUNT(book.id) >= 3" ) public Map<User, List<Book>> loadUserAndBookNames();
אם לא צריך למפות אובייקטים שלמים, אפשר גם להחזיר מיפויים בין
עמודות ספציפיות בשאילתה שלך
keyColumn ו-
valueColumn מאפיינים
בהערה @MapInfo
שיטת השאילתה:
Kotlin
@MapInfo(keyColumn = "userName", valueColumn = "bookName") @Query( "SELECT user.name AS username, book.name AS bookname FROM user" + "JOIN book ON user.id = book.user_id" ) fun loadUserAndBookNames(): Map<String, List<String>>
Java
@MapInfo(keyColumn = "userName", valueColumn = "bookName") @Query( "SELECT user.name AS username, book.name AS bookname FROM user" + "JOIN book ON user.id = book.user_id" ) public Map<String, List<String>> loadUserAndBookNames();
סוגי החזרה מיוחדים
החדר מציע כמה סוגי החזרה מיוחדים לשילוב עם API אחר. של הספריות.
שאילתות עם חלוקה לדפים באמצעות ספריית הדפים
חדר תומך בשאילתות בחלוקה לדפים באמצעות שילוב עם החלוקה לדפים
לספרייה. בחדר 2.3.0-alpha01 ו
גבוהה יותר, DAOs יכולים להחזיר
PagingSource אובייקטים לשימוש
באמצעות מעבר מספר 3.
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM users WHERE label LIKE :query") fun pagingSource(query: String): PagingSource<Int, User> }
Java
@Dao interface UserDao { @Query("SELECT * FROM users WHERE label LIKE :query") PagingSource<Integer, User> pagingSource(String query); }
למידע נוסף על בחירת פרמטרים של סוג עבור PagingSource, ניתן לעיין במאמר
בחירת מפתח וערך
.
גישה ישירה לסמן
אם הלוגיקה של האפליקציה מחייבת גישה ישירה לשורות ההחזרה, אפשר לכתוב
שיטות DAO להחזרת Cursor
כפי שאפשר לראות בדוגמה הבאה:
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5") fun loadRawUsersOlderThan(minAge: Int): Cursor }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5") public Cursor loadRawUsersOlderThan(int minAge); }
מקורות מידע נוספים
כדי לקבל מידע נוסף על גישה לנתונים באמצעות DAOs של חדרים, אפשר לעיין במקורות הבאים: משאבים: