Room Abstract Pojo

I'm creating for fun an android application that tracks the spendings. I'm using Room to persist the user's data and I have POJOs that show the daily/weekly/monthly summaries.

These classes are quite similar, thus I would like to have one abstract POJO that contains the fields and extensions of it that reformat to the correct format. Something like:

public abstract class PeriodInformation {

PeriodInformation(@NonNull Calendar mCalendar, Integer mPeriodSpendingCount, Float mPeriodSpendingSum) {
    this.mCalendar = mCalendar;
    this.mPeriodSpendingCount = mPeriodSpendingCount;
    this.mPeriodSpendingSum = mPeriodSpendingSum;
}

@ColumnInfo(name = "DateTime")
private final Calendar mCalendar;
@ColumnInfo(name = "SpendingCount")
private Integer mPeriodSpendingCount;
@ColumnInfo(name = "SpendingSum")
private Float mPeriodSpendingSum;

// Some other code, e.g., getters, equal override,...
}

Here the extension:

public class WeekInformation extends PeriodInformation{

public WeekInformation(@NonNull Calendar mCalendar, Integer mPeriodSpendingCount, Float mMonthSpendingSum) {
    super(mCalendar, mPeriodSpendingCount, mMonthSpendingSum);
}

@Override
public String getPeriodRepresentation() {
    //return representation;
}

}

However, I get following error message for the WeekInformation Class:

error: Entities and Pojos must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).

So it seems that this is not possible in Room, thus I would be happy to get some suggestion how to not have to copy the same code too often.

thank you.

EDIT: I use following DAO code to aggregate to the POJO, the column calendarDate has following format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX":

@Query("SELECT date(datetime(calendarDate)) AS 'DateTime', count(uID) AS 'SpendingCount', sum(value)  AS 'SpendingSum' from spending GROUP BY date(datetime(calendarDate))")
LiveData<List<DayInformation>> loadDayInformation();

1 answer

  • answered 2018-06-24 11:12 Mikael Ohlson

    I'd think about how your data is structured. SQLite and Room by extension, can do summaries and counts for you, like any other SQL-based DB abstraction, so maybe just represent each spending entry instead.

    Below is a pseudo-code example, I haven't actually tried building this, but it should point you in the right direction.

    public class Spending {
        @ColumnInfo(name = "DateTime")
        private final Long timestamp;
        @ColumnInfo(name = "Expense")
        private Integer expense;
    
       public Spending(long epochTimestampUTC, float expense) {
           this.timestamp = epochTimestampUTC;
           this.expense = expense;
       }
    }
    

    and then in your Data Access Object (DAO) you would construct sums and counts for relevant periods.

    @Dao
    public interface MyDao {
        @Query("SELECT SUM(Expense) FROM spending WHERE DateTime > :startDate AND DateTime <= :endDate")
        public Float calculatePerioExpenses(final long startDate, final long endDate);
    
        @Query("SELECT COUNT(*) FROM spending WHERE DateTime > :startDate AND DateTime <= :endDate")
        public Integer calculatePeriodSpendingCount(final long startDate, final long endDate);
    
    }