android Room库使用问题

补充:

新版的studio增加了查看room数据库的功能。
之前叫 database inspector ,现在的狐狸版本又改名字了,叫 app inspection【这个要求系统是api26以上,也就是8.0的设备最少】
如果没显示,点击view ,第一个tool windows ,然后找上边两个里边的一种就行

资料

https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin/index.html?index=..%2F..index#0
https://github.com/android/sunflower

https://www.jianshu.com/p/2aa8bb141d6e

学习过程记录

照着各种文章写,简单的实现都一样,可跑起来总是挂

java.lang.RuntimeException: cannot find implementation for com.charliesong.roomtest.room.JavaDatabase. JavaDatabase_Impl does not exist
        at androidx.room.Room.getGeneratedImplementation(Room.java:94)
        at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:723)

就是我们那个database类里获取实例Room.databaseBuilder().build(),调用build方法的时候就挂了。
提示很明显,这个database按道理系统应该自动生成一个Impl类的,可我们没有自动生成,可也不知道咋让他自动生成

public abstract class JavaDatabase extends RoomDatabase

各种解决都不行啊,不过好像和kotlin有关,最后我把room相关的类,都改成java写,然后就可以了。
如下

image.png

后记
后来发现,room库分kotlin版本和java版本的,引用的不同的东西,具体用啥,下边有room的文档地址可以查
kotlin写的

apply plugin: 'kotlin-kapt'
    //room
    def room_version = "2.2.5"

    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
    // optional - Kotlin Extensions and Coroutines support for Room
    implementation "androidx.room:room-ktx:$room_version"

java写的

  def room_version = "2.2.5"

  implementation "androidx.room:room-runtime:$room_version"
  annotationProcessor "androidx.room:room-compiler:$room_version"

整理下基本操作

最新的room版本可以到官网查询,20190827目前都2.2了
room

第一步app的build.gradle下添加库

    def room_version = "1.1.1"
    // or, for latest rc, use "1.1.1-rc1"
    implementation "android.arch.persistence.room:runtime:$room_version"
//    annotationProcessor  "android.arch.persistence.room:compiler:$room_version"
    kapt "android.arch.persistence.room:compiler:$room_version"
    // optional - RxJava support for Room
    implementation "android.arch.persistence.room:rxjava2:$room_version"
    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "android.arch.persistence.room:guava:$room_version"
    // Test helpers
    testImplementation "android.arch.persistence.room:testing:$room_version"

或者是androidx的

    def room_version = "2.1.0-alpha02"
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version" // Kotlin 的话用kapt
    // 如果需要用到 rxjava
    implementation "androidx.room:room-rxjava2:$room_version"
    // 如果需要用到 guava
    implementation "androidx.room:room-guava:$room_version"
    // 需要用到相关测试工具的话
    testImplementation "androidx.room:room-testing:$room_version"

如果用kotlin的话,最上边应该是这样的

apply plugin: 'com.android.application'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

另外添加如下注释的地方下边的代码,具体可参考https://blog.csdn.net/hexingen/article/details/78725958

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.charliesong.demo0327"
        minSdkVersion 18
        targetSdkVersion 27
        versionCode 2
        versionName "1.1"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
        //指定room.schemaLocation生成的文件路径
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

添加实体类

当一个类用@Entity注解并且被@Database注解中的entities属性所引用,Room就会在数据库中为那个entity创建一张表。
默认Room会为entity中定义的每一个field都创建一个column。如果一个entity中有你不想持久化的field,那么你可以使用@Ignore来注释它们
另外记得entity必须有一个@PrimaryKey 主键字段

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;
@Entity
public class Userjava {
    @PrimaryKey(autoGenerate = true)
    public int uid;
    public String firstName;
    public String lastName;
    public int age;
    @ColumnInfo(name = "region")//列的名字可以改
    public String address;
}

添加数据访问对象dao

import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;
import java.util.List;
@Dao
public interface UserJavaDao {
    @Insert
    void insertAll(Userjava... userjava);

    @Query("select * from Userjava")
    LiveData<List<Userjava>> getUsersFromSync();

    @Delete
    int delete(Userjava userjava);//参数可以是数组,集合,返回的是删除成功的条数

    @Update
    int update(Userjava... userjava);//参数可以是数组,集合,返回的是update成功的条数
}

database类

版本号必须>=1

import android.arch.persistence.db.SupportSQLiteDatabase;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.arch.persistence.room.migration.Migration;
import android.support.annotation.NonNull;
import com.charliesong.demo0327.app.MyApplication;
//所有的entity注解的类,都得在这里声明
@Database(entities = {Userjava.class},version =4)
public abstract class JavaDatabase extends RoomDatabase {

//定义了几个Dao注解的类,这里就写几个抽象方法
    public abstract UserJavaDao userJavaDao();

    private static JavaDatabase javaDatabase;

    public static JavaDatabase instance(){
        if(javaDatabase==null){
            synchronized (JavaDatabase.class){
                if(javaDatabase==null){
                    javaDatabase= Room.databaseBuilder(MyApplication.myApplication,JavaDatabase.class,"test").
                            addCallback(new Callback() {
                                @Override
                                public void onCreate(@NonNull SupportSQLiteDatabase db) {
                                    super.onCreate(db);
                                    System.out.println("onCreate==========="+db.getVersion()+"==="+db.getPath());
                                }

                                @Override
                                public void onOpen(@NonNull SupportSQLiteDatabase db) {
                                    super.onOpen(db);
                                    System.out.println("onOpen==========="+db.getVersion()+"==="+db.getPath());
                                }
                            })
                            .allowMainThreadQueries()//允许在主线程查询数据
                            .addMigrations(migration)//迁移数据库使用,下面会单独拿出来讲
                            .fallbackToDestructiveMigration()//迁移数据库如果发生错误,将会重新创建数据库,而不是发生崩溃
                            .build();
                }
            }
        }
        return javaDatabase;
    }

    //数据库升级用的
    static Migration migration=new Migration(1,4) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            System.out.println("migrate============"+database.getVersion());
            database.execSQL("ALTER TABLE Userjava "+ " ADD COLUMN address TEXT");
        }
    };
}

然后就可以测试拉。
使用livedata比较方便,只处理数据库的增删改,发生变化livedata自动会变化,我们弄个observer就ok了,列表会自动刷新的

        UtilRoomDB.getUserDao().usersFromSync.observe(this, Observer {
            myAdapter.submitList(it)
        })

我用的listAdapter

inner class  MyAdapter(callback: DiffUtil.ItemCallback<Userjava>): ListAdapter<Userjava, BaseRvHolder>(callback)

顺道记录些其他问题

https://blog.csdn.net/hexingen/article/details/78725958

Error:(22, 17) 警告: Schema export directory is not provided to the annotation processor so we cannot export the schema. 

You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.

方法1
添加 exportSchema = false 就是不需要这个表的json数据

@Database(entities = { YourEntity.class }, version = 1, exportSchema = false)
public abstract class MovieDatabase extends RoomDatabase {
   ...
}

方法2
配置下文件保存的位置
arguments 这个写法可能会引起其他插件异常的,需要注意,比如Hilt库
下边有解决办法
https://stackoverflow.com/questions/62887817/expected-hiltandroidapp-to-have-a-value-did-you-forget-to-apply-the-gradle-plu
就是arguments += 替换arguments = 多个加号

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "com.xingen.architecturecomponents"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        //指定room.schemaLocation生成的文件路径
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }
}

运行以后就能看到下边的东西了,json文件里可以看到我们定义的表以及其包含的字段,主键等信息


image.png

版本升级

https://www.jianshu.com/p/df48fb35a1fe
新版本的库,简单的升级已经不需要我们自己处理了。可以参考下边文章
参考 https://medium.com/androiddevelopers/room-auto-migrations-d5370b0ca6eb
知道升级要添加的方法,可是咋复制老的数据库不记得了,所以还是找别人写的看好了。最讨厌数据库了,2个表就晕了。

打印下可以看到,第一次操作数据库的时候,先create,再open
System.out.println("onCreate==========="+db.getVersion()+"==="+db.getPath());

onCreate===========0===/data/user/0/com.charliesong.demo0327/databases/test
onOpen===========1===/data/user/0/com.charliesong.demo0327/databases/test
升级操作

如果你改了版本,然后没有写Migration,那么升级以后数据库就被清空了。
这两个方法,要么别写,要写了你就得有对应的migration,

//                            .addMigrations(migration,migration2)//迁移数据库使用,下面会单独拿出来讲
//                            .fallbackToDestructiveMigration()//迁移数据库如果发生错误,将会重新创建数据库,而不是发生崩溃

我们一般升级数据库,应该是增加了字段或者修改了字段之类的。

    //数据库升级用的,从版本1升级到版本2
    static Migration migration=new Migration(1,2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            System.out.println("migrate12============"+database.getVersion());
            database.execSQL("ALTER TABLE Userjava "+ " ADD COLUMN country TEXT");
        }
    };

版本2升级到版本4,打算删除表中的一列

如果想改某列的类型,名称啥的也一样操作
.addMigrations(migration,migration2,migration3)
好像drop column不好使,所以就新建个临时表,复制下数据然后删除老的,再把新表名字改回去

    static Migration migration2=new Migration(2,3) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            System.out.println("migrate23============"+database.getVersion());
            database.execSQL("create table aaaa(uid int primary key,firstName text,lastName text,age text,address text)");
            database.execSQL("insert into aaaa select uid  ,firstName ,lastName ,age,address from Userjava");
            database.execSQL("drop table Userjava");
            database.execSQL("alter table  aaaa rename to Userjava");
        }
    };
    static Migration migration3=new Migration(3,4) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            System.out.println("migrate34============"+database.getVersion());
//            database.execSQL("ALTER TABLE Userjava "+ " ADD COLUMN address TEXT");
        }
    };

日志如下,2个print都出来了,然后挂了
看了下,我们上边新建那个aaaa的表,数据类型有点问题,那就改一下


    Process: com.charliesong.demo0327, PID: 30844
    java.lang.IllegalStateException: Migration didn't properly handle Userjava(com.charliesong.demo0327.room.Userjava).
     Expected:
    TableInfo{name='Userjava', columns={address=Column{name='address', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, lastName=Column{name='lastName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, firstName=Column{name='firstName', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, uid=Column{name='uid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, age=Column{name='age', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
     Found:
    TableInfo{name='Userjava', columns={address=Column{name='address', type='text', affinity='2', notNull=false, primaryKeyPosition=0}, lastName=Column{name='lastName', type='text', affinity='2', notNull=false, primaryKeyPosition=0}, firstName=Column{name='firstName', type='text', affinity='2', notNull=false, primaryKeyPosition=0}, uid=Column{name='uid', type='int', affinity='3', notNull=false, primaryKeyPosition=1}, age=Column{name='age', type='text', affinity='2', notNull=false, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
        at com.charliesong.demo0327.room.JavaDatabase_Impl$1.validateMigration(JavaDatabase_Impl.java:75)
        at android.arch.persistence.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:87)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:133)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:256)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:96)
        at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:54)
        at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:233)
        at com.charliesong.demo0327.room.UserJavaDao_Impl$4.compute(UserJavaDao_Impl.java:165)
        at com.charliesong.demo0327.room.UserJavaDao_Impl$4.compute(UserJavaDao_Impl.java:151)
        at android.arch.lifecycle.ComputableLiveData$2.run(ComputableLiveData.java:100)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
        at java.lang.Thread.run(Thread.java:818)

这是成功的日志

11-15 09:15:27.546 com.charliesong.demo0327 I/System.out: migrate23============2
11-15 09:15:27.556 com.charliesong.demo0327 I/System.out: migrate34============2
11-15 09:15:27.606 com.charliesong.demo0327 I/System.out: onOpen===========4===/data/user/0/com.charliesong.demo0327/databases/test

new Migration(4,6) 里边2个版本号到底指的啥

为了测试,
@1 版本从4直接改到8,然后添加2个Migration
new Migration(4,6)和new Migration(4,8)
打印了下,发现只走了4到8
@2 然后版本从8改成11,添加下边2个
new Migration(8,10) new Migration(9,11)
然后2个都没走,然后数据被清空了

看下Migration的查询条件

存储的时候是存在这个集合里的

private SparseArrayCompat<SparseArrayCompat<Migration>> mMigrations =
                new SparseArrayCompat<>();

比如(4,6)和(4,8)那么就是append一个key是4的,然后里边包含的key是6和8的sparsearray
简单分析下,我们只说升级,不说降级。
如下逻辑,从4升级到8,那么根据start=4,找到一个sparsearray,这里包含2个key是6和8,它是倒着来,找到第一个小于等于endVersion也就是8了,这个刚刚好就找一次。
然后分析下从8升级到11,有个(8,10)和(9,11)
先查8,找到一个end10,然后 从10开始查,结果10 没找到,所以返回一个null。因为返回的null。再下边那个方法可以看到,返回null的话数据库就被清空了。

        private List<Migration> findUpMigrationPath(List<Migration> result, boolean upgrade,
                int start, int end) {
            final int searchDirection = upgrade ? -1 : 1;
            while (upgrade ? start < end : start > end) {
                SparseArrayCompat<Migration> targetNodes = mMigrations.get(start);
                if (targetNodes == null) {
                    return null;
                }
                // keys are ordered so we can start searching from one end of them.
                final int size = targetNodes.size();
                final int firstIndex;
                final int lastIndex;

                if (upgrade) {
                    firstIndex = size - 1;
                    lastIndex = -1;
                } else {
                    firstIndex = 0;
                    lastIndex = size;
                }
                boolean found = false;
                for (int i = firstIndex; i != lastIndex; i += searchDirection) {
                    final int targetVersion = targetNodes.keyAt(i);
                    final boolean shouldAddToPath;
                    if (upgrade) {
                        shouldAddToPath = targetVersion <= end && targetVersion > start;
                    } else {
                        shouldAddToPath = targetVersion >= end && targetVersion < start;
                    }
                    if (shouldAddToPath) {
                        result.add(targetNodes.valueAt(i));
                        start = targetVersion;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    return null;
                }
            }
            return result;
        }

这里是调用的方法

    public void onUpgrade(SupportSQLiteDatabase db, int oldVersion, int newVersion) {
        boolean migrated = false;
        if (mConfiguration != null) {
            List<Migration> migrations = mConfiguration.migrationContainer.findMigrationPath(
                    oldVersion, newVersion);
            if (migrations != null) {
                for (Migration migration : migrations) {
                    migration.migrate(db);
                }
                mDelegate.validateMigration(db);
                updateIdentity(db);
                migrated = true;
            }
        }
        if (!migrated) {//如果没找到List<Migration> migrations,那么就会清空表的
            if (mConfiguration != null && !mConfiguration.isMigrationRequiredFrom(oldVersion)) {
                mDelegate.dropAllTables(db);
                mDelegate.createAllTables(db);
            } else {
                throw new IllegalStateException("A migration from " + oldVersion + " to "
                        + newVersion + " was required but not found. Please provide the "
                        + "necessary Migration path via "
                        + "RoomDatabase.Builder.addMigration(Migration ...) or allow for "
                        + "destructive migrations via one of the "
                        + "RoomDatabase.Builder.fallbackToDestructiveMigration* methods.");
            }
        }
    }

添加一个新的entity

错误日志,说这个实体类没有加到database,啥鬼啊,搞不懂。后来才查到,注解那里要添加的,忘了
@Database(entities = {Userjava.class,HourseJava.class},version =1)
public abstract class JavaDatabase extends RoomDatabase

E:\androidStudio\RoomTest\app\src\main\java\com\charliesong\roomtest\room\HourseJavaDao.java:9: 
错误: com.charliesong.roomtest.room.HourseJavaDao 
is part of com.charliesong.roomtest.room.JavaDatabase 
but this entity is not in the database. Maybe you forgot to add com.charliesong.roomtest.room.HourseJava 
to the entities section of the @Database?
    void insertHourse(HourseJava ...hourseJavas);
         ^

添加新的entity步骤

需要在database的注解字段entities里添加,完事需要升级版本号,记得添加migration,
比如你从2升级到3,那么必须添加一个Migration(2,3),否则如果没找到这玩意,数据库就被清空了。还得自己在migration方法里添加create table的命令,建立新表,要不会报错的。

后记

room这东西是编译的时候生成相关的类的,databinding也是,有时候是room这边有问题,导致databinding生成失败,结果你看错误信息都是databinding的。

注解学习

https://blog.csdn.net/hubinqiang/article/details/73012353

错误记录

  1. Cannot figure out how to save this field into database. You can consider adding a type converter for it.
    原因,实体类里有个自定义对象,不认识
public DataType dataType;//这玩意就是个枚举类型

解决办法

    @TypeConverters(DataTypeConverter.class)//注解用哪个类来解析存储数据
    public DataType dataType;

import androidx.room.TypeConverter;

//写一个转化类,其实就是需要两个方法可以互相转化这个自定义类,转化为基本数据类型,也就是可以存入数据库的
public class DataTypeConverter{

    @TypeConverter
    public OneTouchBean.DataType toDataType(int index){
        return OneTouchBean.DataType.values()[index];
    }
    @TypeConverter
    public int toIndex(OneTouchBean.DataType dataType){
        return  dataType.ordinal();
    }
}

这个注解@TypeConverters可以写在要解析的类上边,也可以写在@Database注解的类里,可以参考workManager相关的包里边有,如下代码

@Database(entities = {
        Dependency.class,
        WorkSpec.class,
        WorkTag.class,
        SystemIdInfo.class,
        WorkName.class},
        version = 6)
@TypeConverters(value = {Data.class, WorkTypeConverters.class})
public abstract class WorkDatabase extends RoomDatabase {

kotlin写在属性上,还是报错,必须写在类上边

  1. java.lang.IllegalStateException: getDatabase called recursively

代码如下
在onCreate里,数据库创建成功以后,执行插入一些默认的数据操作,出错了

public abstract class LocalDatabase extends RoomDatabase {
  private static LocalDatabase database;

    public static LocalDatabase instance() {
        if (database == null) {
            synchronized (LocalDatabase.class) {
                if (database == null) {
                    database = Room.databaseBuilder(MainApplication.getCurrentInstance(), LocalDatabase.class, "test").
                            addCallback(new Callback() {
                                @Override
                                public void onCreate(@NonNull SupportSQLiteDatabase db) {
                                    super.onCreate(db);
                                    System.out.println("onCreate===========" + db.getVersion() + "===" + db.getPath());
                                    resetOneTouchData();//这里的代码挂了
                                }

//方法如下,就是插入数据,没别的
private static void resetOneTouchData(){
database.oneTouchDao().insertAll();}

根源就在于db还没关,我们又开了个db
简单的修改,把这个插入数据的操作放到一个新的线程中,让当前的db结束掉就好了。

  1. Entity的实体类,有多个构造方法的时候会出错
    错误: Room cannot pick a constructor since multiple constructors are suitable. Try to annotate unwanted constructors with @Ignore.
    按照提示注解掉多余的,留下一个即可

注意

当初看demo也没看到关闭数据库,所以我也没关,当然,关不关好像对数据没啥影响
如果不关,那么可以看到多了2个临时文件,只有关闭的时候临时文件的数据才会写入db里,否则db文件可能是空的,当然数据没有丢失,你打开还在,不过是在临时文件里而已。

    public static void closeDb(){
        if(javaDatabase!=null){
            javaDatabase.close();
            javaDatabase=null;
        }
    }
image.png

数据库升级,表添加一列问题多多

需求:给表加一列如下的字段
private long placeUID =-1;
完事我就加了

        public void migrate(@NonNull SupportSQLiteDatabase database) {
            final String addColumn="alter table XXXBean add placeUID long default -1";
            database.execSQL(addColumn);
        }

结果挂了,异常提示expected 和found的不一样

Expected:
     placeUID = Column {
            name = 'placeUID', type = 'INTEGER', affinity = '3', notNull = true, primaryKeyPosition = 0, defaultValue = 'null'
        },

Found:
placeUID = Column {
            name = 'placeUID', type = 'Long', affinity = '1', notNull = false, primaryKeyPosition = 0, defaultValue = '-1'
        },

我实体类里定义的是long,实际上room是当做int来处理的,所以,我只好把sql语句改了,类型改成INTEGER 了

final String addColumn="alter table XXXBean add placeUID INTEGER default -1";

完事还是挂,再对比提示信息,还有一个不一样的notNull = true
继续修改

final String addColumn="alter table XXXBean add placeUID INTEGER default -1";

终于完事了,不挂了

后记

没事可以看看work这个库,这里也用到了room,看看人家咋存的


image.png

常用的简单的增删改查

@Dao
public interface MyPlaceDao {
    @Insert
    void insertAll(MyPlaceBean... myPlaceBeans);

    @Insert
    long insertAll(MyPlaceBean myPlaceBeans);

    @Query("select * from MyPlaceBean order by uid desc")
    LiveData<List<MyPlaceBean>> getMyPlacesFromSync();

    @Query("select * from myplacebean where locationData = :json")
    MyPlaceBean getMyPlaceBeanByLocationJson(String json);

//COLLATE NOCASE 忽略大小写
    @Query("select * from myplacebean where changedName = :name COLLATE NOCASE and uid != :uid")
    List<MyPlaceBean> getMyPlaceBeanByChangedName(String name,long uid);

    @Delete
    int delete(MyPlaceBean ...myPlaceBean);//参数可以是数组,集合,返回的是删除成功的条数

    @Delete
    int delete(List<MyPlaceBean> myPlaceBean);//参数可以是数组,集合,返回的是删除成功的条数

    @Update
    int update(MyPlaceBean... myPlaceBeans);//参数可以是数组,集合,返回的是update成功的条数

    @Update
    int update(List<MyPlaceBean> myPlaceBeans);//参数可以是数组,集合,返回的是update成功的条数

    @Query("update myplacebean set changedName = :name where uid = :uid")
    int updateName(String name, long uid);
}

需要注意下,这里返回的只能是List,而不能是ArrayList,否则编译就挂了
LiveData<List<MyPlaceBean>> getMyPlacesFromSync();

kotlin需要注意的地方

TypeConverters注解是写在class上了,
下边这个自增的主键要写到构造方法里,否则,它没法自动生成id,默认就是个0
@PrimaryKey(autoGenerate = true)
var id:Int=0

@Entity
@TypeConverters(DataTypeConverter::class)
data class Task(
    val name: String,
    val deadline: String,
     val priority: TaskPriority =TaskPriority.MEDIUM ,
    var completed: Boolean = false,
    @PrimaryKey(autoGenerate = true)
    var id:Int=0
)

比如这样写,你会发现数据库里id都是0

data class Task(
    val name: String,
    val deadline: String,
     val priority: TaskPriority =TaskPriority.MEDIUM ,
    var completed: Boolean = false
){
    @PrimaryKey(autoGenerate = true)
    var id:Int=0
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容