כשמשתמשים בספריית הקבועות של החדרים כדי לאחסן את נתוני האפליקציה, אפשר ליצור אינטראקציה בנתונים המאוחסנים באמצעות הגדרה של אובייקטים של גישה לנתונים או 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 של חדרים, אפשר לעיין במקורות הבאים: משאבים: