android专题-数据库room

作者: 浪人残风 | 来源:发表于2021-02-24 13:49 被阅读0次

    Room介绍

    room是Google官方推荐的ORM数据库框架,抽象出sqlite访问的数据库。
    包含三大组件:

    • Entity 定义 表结构,每个entity类对一个表,默认会把entity类所有字段都创建为表字段
    • Dao 定义entity类的CRUD(增删查改)功能
    • Database 数据库的访问入口,注解定义数据库的实体表,数据库版本控制,表结构导出、表结构修改等都在这里处理

    步骤

    1.添加依赖

     def room_version = '2.3.0-alpha04'
    
     implementation rootProject.ext.dependencies.room_runtime
     annotationProcessor rootProject.ext.dependencies.room_compiler
     androidTestImplementation rootProject.ext.dependencies.room_testing
    

    2.定义Entity实体表

    @Entity 注解并在@Database 注解中的 entities 属性所引用,Room就会在数据库中为这个被 @Entity 注解的类创建一张表
    @PrimaryKey 每个entity至少要有一个主键(PrimaryKey),autoGenerate表示这个值自动生成
    @Entity(primaryKeys = {"xxx", "xxx"}) 如果是复合主键的话, 你需要使用注解@Entity的primaryKeys属性

    @Entity(primaryKeys = {"firstName", "lastName"})
    public class User {
        public String firstName;
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    

    @ColumnInfo(name = "xxx") 定义表字段,也可以不使用此注解,默认为所有属性生成表字段
    @Ignore 如果Engity类中某个属性不想保存到数据库,可以使用@Ignore注解忽略

    @Entity
    public class User {
        @PrimaryKey
        public int id;
        public String firstName;
        public String lastName;
        @Ignore
        Bitmap picture;
    }
    

    @Entity(indices = {@Index("name"), @Index(value = {"last_name", "address"})}) 为了加速查询速度. 要给实体添加索引

    @Entity(indices = {@Index("name"),
            @Index(value = {"last_name", "address"})})
    public class User {
        @PrimaryKey
        public int id;
        public String firstName;
        public String address;
    
        @ColumnInfo(name = "last_name")
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    

    @Entity(foreignKeys = @ForeignKey(entity = User.class,
    parentColumns = "id",
    childColumns = "user_id")) 设置外键

    @Entity(foreignKeys = @ForeignKey(entity = User.class,
                                      parentColumns = "id",
                                      childColumns = "user_id"))
    public class Book {
        @PrimaryKey
        public int bookId;
        public String title;
        @ColumnInfo(name = "user_id")
        public int userId;
    }
    

    @Embedded注解来表示一个对象

    public class Address {
        public String street;
        public String state;
        public String city;
        @ColumnInfo(name = "post_code")
        public int postCode;
    }
    @Entity
    public class User {
        @PrimaryKey
        public int id;
    
        public String firstName;
    
        @Embedded
        public Address address;
    }
    

    demo:

    package com.wrs.project.module.app.common.database.entity;
    import androidx.room.Entity;
    import androidx.room.PrimaryKey;
    import androidx.annotation.NonNull;
    
    @Entity(tableName = "Article")
    public class Article {
        @PrimaryKey(autoGenerate = true)
        private int id;
    
        private String author;
        private String title;
        private String content;
    
        private String token;
        private int comments;
    
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getToken() {
            return token;
        }
    
        public void setToken(String token) {
            this.token = token;
        }
    
        public int getComments() {
            return comments;
        }
    
        public void setComments(int comments) {
            this.comments = comments;
        }
    }
    
    

    3. 定义DAO

    简单查询

    @Dao
    public interface MyDao {
        @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);
    }
    

    嵌套查询

    @Dao
    public interface MyDao {
        @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
    public interface MyDao {
       @Query("SELECT user.name AS userName, pet.name AS petName "
              + "FROM user, pet "
              + "WHERE user.id = pet.user_id")
       public LiveData<List<UserPet>> loadUserAndPetNames();
    
    
       // You can also define this class in a separate file, as long as you add the
       // "public" access modifier.
       static class UserPet {
           public String userName;
           public String petName;
       }
    }
    

    demo

    package com.wrs.project.module.app.common.database.dao;
    
    import androidx.lifecycle.LiveData;
    import androidx.room.Dao;
    import androidx.room.Delete;
    import androidx.room.Insert;
    import androidx.room.OnConflictStrategy;
    import androidx.room.Query;
    import androidx.room.Update;
    
    import com.wrs.project.module.app.common.database.entity.Article;
    
    import java.util.List;
    
    @Dao
    public interface ArticleDao {
        /**
         * 增
         * @param entities
         */
        @Insert
        void insert(Article... entities);
    
        /**
         * 删
         * @param entities
         */
        @Delete
        void delete(Article... entities);
    
        /**
         * 查
         * @param title
         */
        @Query("SELECT * FROM Article WHERE title = :title")
        List<Article> findByTitle(String title);
    
        /**
         * 查
         * @param titles
         */
        @Query("SELECT * FROM Article WHERE title IN (:titles)")
        List<Article> findInTitles(List<String> titles);
    
        /**
         * 改
         * @param entities
         */
        @Update
        void update(Article... entities);
    
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        List<Long> insertAll(List<Article> entities);
    
        @Delete
        void delete(Article entity);
    
        @Query("DELETE FROM Article")
        void deleteAll();
    
        @Delete
        void deleteArticle(Article entity);
    
        @Query("SELECT * FROM Article")
        List<Article> findAll();
    
        @Query("SELECT * FROM Article")
        LiveData<List<Article>> loadSignList();
    }
    
    

    4. 定义Database

    package com.wrs.project.module.app.common.database;
    
    import android.content.Context;
    
    import androidx.room.Room;
    import androidx.room.RoomDatabase;
    import androidx.room.TypeConverters;
    import androidx.room.migration.Migration;
    import androidx.sqlite.db.SupportSQLiteDatabase;
    
    import com.wrs.project.module.app.common.database.conversion.ConversionFactory;
    import com.wrs.project.module.app.common.database.dao.ArticleDao;
    import com.wrs.project.module.app.common.database.entity.Article;
    
    @androidx.room.Database(
            entities = { Article.class}, // 声明需要创建表的实体
            version = 2, // 数据库版本号
            exportSchema = true  // 表结构是否需要导出
    )
    @TypeConverters({ConversionFactory.class}) // 属性类型转换,这里值转换了Date类
    public abstract class Database extends RoomDatabase {
        public abstract ArticleDao articleDao(); // 声明每个entity的dao类
    
        private static Database sInstance; // 创建访问数据库比较耗资源,生成单例方便访问
        public static Database getInstance(final Context context) {
            if (sInstance == null) {
                synchronized (Database.class) {
                    if (sInstance == null) {
                        sInstance = create(context.getApplicationContext());
                    }
                }
            }
            return sInstance;
        }
    
    
        private static Database create(final Context context) {
            return Room.databaseBuilder(
                    context,
                    Database.class,
                    "phonesign_db")
                    .addMigrations(MIGRATION_1_2) // 构建版本升级时表结构的变化
                    .allowMainThreadQueries()
                    .build();
        }
    
        private static Migration MIGRATION_1_2 = new Migration(1,2) {
            @Override
            public void migrate(SupportSQLiteDatabase database) {
                database.execSQL("ALTER TABLE Article "
                        + " ADD COLUMN token TEXT");
                database.execSQL("ALTER TABLE Article "
                        + " ADD COLUMN comments INTEGER NOT NULL DEFAULT 0");
            }
        };
    }
    
    

    5. 测试

    package com.wrs.project.module.app.common;
    
    import android.content.Context;
    import android.util.Log;
    
    import androidx.test.ext.junit.runners.AndroidJUnit4;
    import androidx.test.platform.app.InstrumentationRegistry;
    
    import com.wrs.project.module.app.common.database.DBService;
    import com.wrs.project.module.app.common.database.entity.Article;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import static org.junit.Assert.assertEquals;
    
    @RunWith(AndroidJUnit4.class)
    public class DatabaseInstrumentedTest {
        @Test
        public void useAppContext() {
            // Context of the app under test.
            Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
            AppMgr.context = appContext;
            AppMgr.debug = true;
    
            List<Article> list = new ArrayList<>();
            for (int i = 0; i < 6; i++) {
                Article entity = new Article();
    
                entity.setTitle("title" + i);
                entity.setDate(new Date());
                list.add(entity);
            }
            DBService.insertAll(list);
    
            List<Article> resultList = DBService.findAll();
            if (null != resultList && resultList.size() > 0) {
                for (int i = 0; i < resultList.size(); i++) {
                    Article entity = resultList.get(i);
                    Log.e("article", entity.getTitle());
                }
            }
    
            List<Article>  entityList = DBService.findByTitle("title5");
            Log.e("article", entityList.toString());
        }
    }
    
    

    如果觉得可以就点个👍吧,欢迎粉丝收藏,土豪打赏,您的关注就是我们创作的动力!

    读者有什么想看的相关技术篇章,欢迎评论留言!

    QQ交流群:908058499

    项目源码:https://codechina.csdn.net/android1/projectbasic

    上篇:无 目录 下篇:android专题-蓝牙扫描、连接、读写

    相关文章

      网友评论

        本文标题:android专题-数据库room

        本文链接:https://www.haomeiwen.com/subject/ytlsfltx.html