在Room中创建Generic DAO接口时“参数类型必须是@Entity注解的类”

问题描述 投票:0回答:18

我正在使用 Room 架构组件来实现持久化。我创建了通用 DAO 接口以避免样板代码。 房间专业提示

但是我的代码无法编译并显示“错误:(21, 19) 错误:参数的类型必须是用 @Entity 注释的类或其集合/数组。”对于通用类 T。

interface BaseDao<T> {

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(T... entity);

@Update
void update(T entity);

@Delete
void delete(T entity);
}

@Dao
public abstract class ReasonDao implements BaseDao<ReasonDao> {

   @Query("SELECT * from Reason")
   abstract public List<Reason> getReasons();

}

我这里有什么遗漏的吗? 它的工作原理如下这里

java android persistence dao android-room
18个回答
53
投票

在 gradle 中对此进行了更改:

kapt "androidx.room:room-compiler:$roomVersion"

对此:

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

13
投票

我最初遵循 Kotlin 中使用的方法,但这在 Java 代码中给出了错误。 两个快速更改为我解决了这个问题

  • 将 BaseDao 更改为抽象类
  • 在 BaseDao 中添加了 @Dao 注解

请找到下面的代码,现在它可以正常运行了

@Dao
abstract class BaseDao<T> {

   @Insert(onConflict = OnConflictStrategy.REPLACE)
   abstract void insert(T entity);

   @Update
   abstract void update(T entity);

   @Delete
   abstract void delete(T entity);
 }

 @Dao
 public abstract class ReasonDao extends BaseDao<Reason>{

    @Query("SELECT * from Reason")
    abstract public List<Reason> getReasons();

  }

8
投票

如果您在 Kotlin 1.7.10+ 和 Room 中遇到此问题 < 2.4.2, upgrading Room to 2.4.3 fixes the issue.

来自 Room 2.4.3 的变更日志: 修复了导致 Room 无法识别 Kotlin 1.7 中的挂起函数的问题

此问题是由于在接口中使用

suspend
函数进行插入/删除造成的: https://issuetracker.google.com/issues/236612358


6
投票

问题是在我的build.gradle中,我使用的Kotlin版本是1.5.0

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.0"

但据我了解,这个版本的 Kotlin 以及 Room 和协程并不能很好地工作。 通过将 Kotlin 版本降级至以下解决了该问题:

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.32"

解决了!稍后谢谢我


5
投票

原因是您指定了 ReasonDao 类型作为泛型参数,而不是 Reason

原代码:

@Dao
public abstract class ReasonDao implements BaseDao<ReasonDao> {

   ...

}

正确代码:

@Dao
public abstract class ReasonDao implements BaseDao<Reason> {

   ...

}

其中 Reason 是用 @Entity 注释标记的类型。

顺便说一句,这已在接受的答案中修复,但在更改列表中未提及:)


4
投票

在 gradle 中将此: kapt "androidx.room:room-compiler:$roomVersion" 更改为:annotationProcessor "androidx.room:room-compiler:$room_version"

执行此解决方案对我有部分帮助,但当尝试在数据库中插入日期时,它对我不起作用,因此尝试 kapt "androidx.room:room-compiler:$roomVersion" 并将 room_version 更改为最新的稳定版本https: //developer.android.com/jetpack/androidx/releases/room#groovy 附属项 {

//**
def room_version = '2.4.0'
def activityVersion = '1.4.0'
def lifecycle_version = "2.2.0"
// Room and Lifecycle dependencies
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
//kotlin extensions for coroutine support with room
implementation("androidx.room:room-ktx:$room_version")

//kotlin extension for coroutine support with activities
implementation "androidx.activity:activity-ktx:$activityVersion"
//**

这对我来说是正确的工作方式


2
投票

这是版本错误。尝试更新您的房间依赖项。

我将我的更改为:

implementation "androidx.room:room-runtime:2.2.5"

致:

implementation "androidx.room:room-runtime:2.4.2"


2
投票

去掉暂停就可以了。

@Dao
interface FoodDao {

     @Insert(onConflict = OnConflictStrategy.REPLACE)
     fun upsert(meal: Meal): Long


    @Query("SELECT * FROM food_tables")
    fun getAllFood(): LiveData<List<Meal>>


    @Delete
    fun deleteFood(meal: Meal)

}

1
投票

就我而言,我尝试保存到数据库非实体对象。然后替换为实体类(包含

@Entity(tableName = "your_table", indices = [Index("your_key")])
)。


1
投票

我相信您错过了为 T 类提供

Entity
注释。例如
Reason
类应该有
@Entity
并将其交给 ReasonDao 类。喜欢:

@Dao
 public abstract class ReasonDao extends BaseDao<Reason>{}


1
投票

请勿将

kapt
替换为
annotationProcessor

试试这个吧

def room_version = "2.5.1"

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

// To use Kotlin annotation processing tool (kapt)
kapt "androidx.room:room-compiler:$room_version"

// To use Coroutine features with room
implementation "androidx.room:room-ktx:$room_version"

0
投票

这里缺少的是 Data 类。一般来说, @Entity代表你要存储的对象,

  • 房间实体包含
  • 内每列的字段
  • 数据库中的表
@Entity(tableName="something") data class YourData()
            

0
投票

对于那些在 dao 中使用 Kotlin 时遇到“参数类型必须是用 @Entity 注释的类或其集合/数组”错误的人,您应该尝试在函数上使用 @JvmSuppressWildcards 注释。例如。

 @Query("SELECT * FROM materials")
 @JvmSuppressWildcards
 fun getAllMaterials(): LiveData<List<MaterialModel>>

0
投票

在我的例子中,我试图将数据类对象存储到房间数据库中。该错误表明

Insert
的参数应该是一个具有
@Entity
注释的类,因此我创建了一个与数据类具有相同值的表(实体)并成功存储了它们


0
投票

我犯的一个小错误是 我没有使用 @Entity 注释来注释我的数据类

表声明

@Entity // Check if you have used this annotation or not
data class fooTable(){
...
}

在 DAO 中

@Dao
interface myDao{
  @Insert
  suspend fun addFoo(fooObj: fooTable)
  }
}

如果您尝试在 Room DB 的表中插入一行,则应使用 @Entity 注释来注释相应的数据类


0
投票

实际上更改版本房间也很重要,就像我将房间版本从 2.2.6 更改为 2.4.3 并且它有效。如果 Kotlin 版本低,最好也使用较低版本的 Room;如果 Kotlin 版本高,最好也使用较高版本。


0
投票

就我而言,依赖版本问题。我已经升级依赖现在工作正常。 因此请确保依赖关系符合 kotlin 版本。

**def room_version = "2.5.1"**
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"

0
投票

当我在方法中不小心使用vararg时遇到了这个问题:

@Insert
fun insertAll(vararg postDbModels: Array<PostDbModel>)

为了解决这个问题,我刚刚删除了 vararg 并使用 @Entity 类模型数组代替:

@Insert
fun insertAll(postDbModels: Array<PostDbModel>)
© www.soinside.com 2019 - 2024. All rights reserved.