Android ROOM: как вернуть псевдоним столбца, который не сохранен - PullRequest
0 голосов
/ 15 октября 2019

ЦЕЛЬ

Уметь возвращать вычисленные и псевдонимы столбцов, не сохраняя их

ЧТО ПРОБОВАНО

Использованиеэтот фрагмент ниже, я хочу получить studentCount без необходимости создания соответствующего столбца:

SELECT i.*, (
        SELECT COUNT(s.id) 
        FROM students s 
        WHERE s.instructorId = i.id
    ) AS studentCount 
FROM instructors i

Мои модели POJO выглядят так:

@Entity
public class Student {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private String firstName, lastName;
    private long instructorId;

    public long getId(){ return id; }
    public long getInstructorId(){ return instructorId; }
    public String getFirstName(){ return firstName; }
    public String getLastName(){ return lastName; }

    public void setId(long id){ this.id = id; }
    public void setInstructorId(long id){ this.instructorId = id; }
    public void setFirstName(String firstname){ this.firstName = firstName; }
    public void setLastName(String lastname){ this.lastname = lastname; }
}

public class NestingClass {
    public int studentCount;
}

@Entity
public class Instructor {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private String fullNname;

    @Embedded
    private NestingClass studentCount; // Do not persist

    public long getId(){ return id; }
    public String getFullName(){ return fullName; }
    public Nestingclass getStudentCount(){ return studentCount; }

    public void setId(long id){ this.id = id; }
    public void setFullName(String fullName){ this.fullName = fullName; }
    public void setStudentCount(NestingClass sc){ this.studentCount = sc; }
}

ТЕКУЩЕЕ ПОВЕДЕНИЕ

Запрос работает, но в результирующей базе данных создается соответствующий столбец для studentCount, который противоположен тому, что я хотел бы иметь.

Кроме того, если я удалюаннотацию @Embedded и использование @Ignore, я получаю ошибку об отсутствующем столбце.

Если я изменяю тип динамического столбца на его собственный тип, я получаю ошибку о том, что поле не может бытьбыть преобразованным в сущность.

ОЖИДАЕМОЕ ПОВЕДЕНИЕ

То же, что и цель


Итак, как я могу выполнить вышеуказанный запрос без Roomсоздать столбец?

1 Ответ

0 голосов
/ 16 октября 2019

Я полагаю, что вы делаете это в порядке, обратном тому, что вы должны делать.

Рассмотрите следующее, где

NestingClass.java : -

public class NestingClass {
    public int studentCount;
    @Embedded
    Instructor instructor;

    public NestingClass(StudentInstructorDao studentInstructorDao, int instructorId) {
        this.instructor = studentInstructorDao.getInstructor(instructorId);
        this.studentCount = studentInstructorDao.getStudentCount(instructorId);
    }

    public Instructor getInstructor() {
        return instructor;
    }

    public void setInstructor(Instructor instructor) {
        this.instructor = instructor;
    }

    public int getStudentCount() {
        return studentCount;
    }

    public void setStudentCount(int studentCount) {
        this.studentCount = studentCount;
    }
}
  • , т. Е. Инструктор был встроен.

и Instructor.class : -

@Entity
public class Instructor {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private String fullNname;

    public long getId(){ return id; }
    public String getFullNname() { return fullNname; }
    public void setId(long id){ this.id = id; }
    public void setFullNname(String fullName){ this.fullNname = fullName; }
}
  • т.е. число студентов не является частью Инструктора

И Dao StudentInstructorDao.java является: -

@Dao
public interface StudentInstructorDao {

    @Insert
    long insertStudent(Student student);

    @Insert
    long[] insertStudents(Student... students);

    @Insert
    long insertInstructor(Instructor instructor);

    @Insert
    long[] insertInstructors(Instructor... instructors);

    @Query("SELECT * FROM Instructor WHERE id = :instructorId")
    Instructor getInstructor(long instructorId);

    @Query("SELECT count() FROM Instructor JOIN student ON student.instructorId = Instructor.id WHERE Instructor.id = :instructorId" )
    int getStudentCount(long instructorId);
}

Следующий код тестирования:-

    mStudentInstructorDao = mDatabase.studentInstructorDao();
    Instructor i1 = new Instructor();
    i1.setFullNname("I1");
    Instructor i2 = new Instructor();
    i2.setFullNname("I2");
    mStudentInstructorDao.insertInstructors(i1,i2);
    Student s1 = new Student();
    s1.setFirstName("S1");
    s1.setLastName("LS1");
    s1.setInstructorId(1);
    Student s2 = new Student();
    s2.setFirstName("S1");
    s2.setInstructorId(1);
    s2.setLastName("LS2");
    mStudentInstructorDao.insertStudents(s1,s2);
    NestingClass nc = new NestingClass(mStudentInstructorDao,1);
    Log.d("INSTRUCTORINFO","Instructor " + nc.getInstructor().getFullNname() + " has " + nc.getStudentCount() + " Students");

Результаты при запуске в журнале, содержащем: -

2019-10-16 09:05:53.472 D/INSTRUCTORINFO: Instructor I1 has 2 Students

Альтернатива

Альтернативным подходом может быть отказ от NestingClass и иметь Instructor.class as

@Entity
public class Instructor {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private String fullNname;

    public long getId(){ return id; }
    public String getFullNname() { return fullNname; }
    public void setId(long id){ this.id = id; }
    public void setFullNname(String fullName){ this.fullNname = fullName; }
    //<<<<<<<<< ADDED >>>>>>>>
    public int getStudentCount(StudentInstructorDao studentInstructorDao) {
        return studentInstructorDao.getStudentCount(this.id);
    }
}

Использование: -

    Instructor i = mStudentInstructorDao.getInstructor(1);
    Log.d("STUDENTCOUNT","Instructor " + i.getFullNname() + " has " + i.getStudentCount(mStudentInstructorDao) + " Students");

приводит к (для тех же данных): -

2019-10-16 09:33:39.582 D/STUDENTCOUNT: Instructor I1 has 2 Students
...