You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Room DAO无法识别DatabaseView问题求助

Android Room视图查询异常:Database Inspector可查但DAO找不到视图

问题描述

Database Inspector可正常执行视图查询,但Room在DAO中无法找到对应视图,始终报错。已尝试升级数据库版本、重建视图、清理重建项目及设置viewName属性,问题仍未解决。

原始代码

视图类

package Vistas;

import androidx.room.DatabaseView;

@DatabaseView("SELECT Alumno.id_alumno,Alumno.primer_apellido_alumno,Alumno.segundo_apellido_alumno,Alumno.nombre_alumno,Matricula.ano_matricula, Grado.nombre_grado FROM Alumno JOIN Matricula ON Alumno.id_alumno = Matricula.id_alumno_matricula JOIN Grado ON Grado.id_grado = Matricula.id_grado_matricula")
public class AlumnoVista {
    public Integer alumnoId;
    public String primerApellido;
    public String segundoApellido;
    public String nombreAlumno;
    public String nombreGrado;
    public Integer anoMatricula;
}

数据库类

package Controlador;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.room.DatabaseConfiguration;
import androidx.room.InvalidationTracker;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;

import Vistas.AlumnoVista;
import entidades.Alumno;
import entidades.Asignatura;
import entidades.Centro;
import entidades.Grado;
import entidades.Matricula;
import entidades.Nota;
import entidades.Profesor;
import entidades.Usuario;
import entidadesDao.AlumnoDao;
import entidadesDao.AsignaturaDao;
import entidadesDao.CentroDao;
import entidadesDao.MatriculaDao;
import entidadesDao.NotaDao;
import entidadesDao.ProfesorDao;
import entidadesDao.UsuarioDao;
import entidadesDao.GradoDao;

@androidx.room.Database(entities = {Alumno.class, Asignatura.class, Centro.class, Profesor.class, Usuario.class, Nota.class, Matricula.class, Grado.class},
        views = {AlumnoVista.class},
        version=5, exportSchema = false)
public abstract class BaseDatos extends RoomDatabase {
    private static final String DB_NAME = "database";
    private static BaseDatos instance;

    public abstract AlumnoDao alumnoDao();

    public abstract GradoDao gradoDao();

    public abstract CentroDao centroDao();

    public abstract AsignaturaDao asignaturaDao();

    public abstract ProfesorDao profesorDao();

    public abstract UsuarioDao usuarioDao();

    public abstract MatriculaDao matriculaDao();

    public abstract NotaDao notaDao();

    public static BaseDatos getInstance(Context context) {
        if (instance == null){
            instance = Room.databaseBuilder(context.getApplicationContext(), BaseDatos.class, DB_NAME).fallbackToDestructiveMigration().createFromAsset("database.db").build();
        }
        return instance;
    }

    @Override
    public void clearAllTables() {

    }

    @NonNull
    @Override
    protected InvalidationTracker createInvalidationTracker() {
        return null;
    }

    @NonNull
    @Override
    protected SupportSQLiteOpenHelper createOpenHelper(@NonNull DatabaseConfiguration databaseConfiguration) {
        return null;
    }
}

DAO类

package entidadesDao;

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 java.util.List;

import Vistas.AlumnoVista;
import entidades.Alumno;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Flowable;

@Dao
public interface AlumnoDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public Completable insertAlumno(Alumno alumno);

    @Update
    public Completable updateAlumno(Alumno alumno);

    @Delete
    public Completable deleteAlumno(Alumno alumno);

    @Query("SELECT * FROM Alumno ORDER BY primer_apellido_alumno ASC")
    public Flowable<List<Alumno>> getAlumnosByFirstName();

    @Query("SELECT * FROM AlumnoVista")
    public List<AlumnoVista> getAlumnosVista();
}

解决方案

1. 修正视图类字段与SQL列的映射

Room默认通过字段名匹配SQL查询返回的列名,你的AlumnoVista字段名和SQL列名不匹配,需添加@ColumnInfo注解指定对应关系:

package Vistas;

import androidx.room.ColumnInfo;
import androidx.room.DatabaseView;

@DatabaseView("SELECT Alumno.id_alumno,Alumno.primer_apellido_alumno,Alumno.segundo_apellido_alumno,Alumno.nombre_alumno,Matricula.ano_matricula, Grado.nombre_grado FROM Alumno JOIN Matricula ON Alumno.id_alumno = Matricula.id_alumno_matricula JOIN Grado ON Grado.id_grado = Matricula.id_grado_matricula")
public class AlumnoVista {
    @ColumnInfo(name = "id_alumno")
    public Integer alumnoId;
    @ColumnInfo(name = "primer_apellido_alumno")
    public String primerApellido;
    @ColumnInfo(name = "segundo_apellido_alumno")
    public String segundoApellido;
    @ColumnInfo(name = "nombre_alumno")
    public String nombreAlumno;
    @ColumnInfo(name = "nombre_grado")
    public String nombreGrado;
    @ColumnInfo(name = "ano_matricula")
    public Integer anoMatricula;
}

2. 检查预打包数据库中的视图

你使用createFromAsset("database.db")加载预打包数据库,Room不会自动为预打包数据库创建视图,需手动在预打包数据库中创建AlumnoVista视图,确保其结构和@DatabaseView中的SQL一致。

3. 移除RoomDatabase的无效重写方法

你的BaseDatos类重写了clearAllTables()、createInvalidationTracker()、createOpenHelper()方法,这些空实现会破坏Room的正常运行逻辑,移除后恢复Room默认行为:

package Controlador;

import android.content.Context;

import androidx.room.Room;
import androidx.room.RoomDatabase;

import Vistas.AlumnoVista;
import entidades.Alumno;
import entidades.Asignatura;
import entidades.Centro;
import entidades.Grado;
import entidades.Matricula;
import entidades.Nota;
import entidades.Profesor;
import entidades.Usuario;
import entidadesDao.AlumnoDao;
import entidadesDao.AsignaturaDao;
import entidadesDao.CentroDao;
import entidadesDao.MatriculaDao;
import entidadesDao.NotaDao;
import entidadesDao.ProfesorDao;
import entidadesDao.UsuarioDao;
import entidadesDao.GradoDao;

@androidx.room.Database(entities = {Alumno.class, Asignatura.class, Centro.class, Profesor.class, Usuario.class, Nota.class, Matricula.class, Grado.class},
        views = {AlumnoVista.class},
        version=5, exportSchema = false)
public abstract class BaseDatos extends RoomDatabase {
    private static final String DB_NAME = "database";
    private static BaseDatos instance;

    public abstract AlumnoDao alumnoDao();

    public abstract GradoDao gradoDao();

    public abstract CentroDao centroDao();

    public abstract AsignaturaDao asignaturaDao();

    public abstract ProfesorDao profesorDao();

    public abstract UsuarioDao usuarioDao();

    public abstract MatriculaDao matriculaDao();

    public abstract NotaDao notaDao();

    public static BaseDatos getInstance(Context context) {
        if (instance == null){
            instance = Room.databaseBuilder(context.getApplicationContext(), BaseDatos.class, DB_NAME)
                    .fallbackToDestructiveMigration()
                    .createFromAsset("database.db")
                    .build();
        }
        return instance;
    }
}

4. 统一DAO方法的返回类型

为避免线程问题,建议getAlumnosVista()方法使用RxJava的Flowable类型,和其他方法保持一致:

@Query("SELECT * FROM AlumnoVista")
public Flowable<List<AlumnoVista>> getAlumnosVista();

内容的提问来源于stack exchange,提问作者JonnerBill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:33:14