Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store currency in ROOM DB?

I have entity:

@Entity(tableName = "products")
public class Product{

    @PrimaryKey(autoGenerate = true)
    private Long id;

    @ColumnInfo(name = "amount")
    private BigDecimal amount;

I need store it in Room DB. I Can not store BigDecimal and I create converter:

public static class Converters {
        @TypeConverter
        public BigDecimal fromString(String value) {
            return value == null ? null : new BigDecimal(value);
        }

        @TypeConverter
        public Double amountToString(BigDecimal bigDecimal) {
            if (bigDecimal == null) {
                return null;
            } else {
                return bigDecimal.doubleValue();
            }
        }
    }

and add to column:

@TypeConverters(Converters.class)
    @ColumnInfo(name = "amount")
    private BigDecimal amount;

Now I store currency in double column. And I want method for summ totalcurrency:

@Query("SELECT SUM(amount) FROM products")
LiveData<Double> totalSum();

But I think it is bad way, because I can lose some values when converting.

My question: How can I ctore currency in ROOM DB? and return method

LiveData<BigDecimal> totalSum();
like image 550
ip696 Avatar asked Dec 05 '17 10:12

ip696


People also ask

What is room DB?

Room is one of the Jetpack Architecture Components in Android. This provides an abstract layer over the SQLite Database to save and perform the operations on persistent data locally.

How do I delete data from kotlin room database?

3.1 Add the Clear all data menu option In MainActivity , implement the onOptionsItemSelected() method to invoke the deleteAll() method on the WordViewModel object. Run your app. In the Options menu, select Clear all data. All words should disappear.


1 Answers

Instead of Long vs BigDecimal converters, I'm using between String and BigDecimal.

Warning: With this way, you can't use SUM, TOTAL or other expression with Room DB. Because my purpose for app is using many currencies, so I manually retrieve data and calculate based on current exchange rates.

class BigDecimalTypeConverter {

    @TypeConverter
    fun bigDecimalToString(input: BigDecimal?): String {
        return input?.toPlainString() ?: ""
    }

    @TypeConverter
    fun stringToBigDecimal(input: String?): BigDecimal {
        if (input.isNullOrBlank()) return BigDecimal.valueOf(0.0)
        return input.toBigDecimalOrNull() ?: BigDecimal.valueOf(0.0)
    }

}

if you only have one currency, you can use Double instead of String:

class BigDecimalDoubleTypeConverter {

    @TypeConverter
    fun bigDecimalToDoubleinput: BigDecimal?): Double {
        return input?.toDoubleOrNull() ?: 0.0
    }

    @TypeConverter
    fun stringToBigDecimal(input: Double?): BigDecimal {
        if (input == null) return BigDecimal.ZERO
        return BigDecimal.valueOf(input) ?: BigDecimal.ZERO
    }

}

So you can retrieve SUM, TOTAL,... from Dao:

@Query("SELECT SUM(transactions.amounts) FROM transactions WHERE transactions.timestamp >= :fromDateTimestamp")
fun getTotalAmount(fromDateTimestamp: Long): Double

Hope it help!

like image 198
dphans Avatar answered Sep 22 '22 01:09

dphans