android 如何在ROOM DB中存储货币?

hiz5n14c  于 2023-01-28  发布在  Android
关注(0)|答案(3)|浏览(139)

我有实体:

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

    @PrimaryKey(autoGenerate = true)
    private Long id;

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

我需要将其存储在房间数据库中。我不能存储BigDecimal,我创建转换器:

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();
            }
        }
    }

并添加到列:

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

现在我把货币存储在双列中。我需要summtotalcurrency的方法:

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

但我认为这是不好的方式,因为我可以失去一些价值观时,转换。
我的问题:如何在ROOM DB中创建货币?以及返回方法

LiveData<BigDecimal> totalSum();
2vuwiymt

2vuwiymt1#

我使用的不是LongBigDecimal转换器,而是介于StringBigDecimal之间的转换器。
警告:使用这种方式,您不能使用SUMTOTAL或其他表达式与房间数据库。因为我的应用程序的目的是使用多种货币,所以我手动检索数据并根据当前汇率计算。

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)
    }

}

如果只有一种货币,可以使用Double代替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
    }

}

因此,您可以从Dao检索SUMTOTAL ......:

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

在数据库上使用TypeConverter

@Database(...)
@TypeConverters(BigDecimalTypeConverter::class)
internal abstract class AppDatabase : RoomDatabase() {
   ...
}
3phpmpom

3phpmpom2#

你可以用long存储你的值。如果你在序列化的时候得到了1.55,把它乘以100,然后把long存储在db中。当你反序列化的时候,用这个long创建BigDecimal,然后除以100

public static class Converters {
        @TypeConverter
        public BigDecimal fromLong(Long value) {
            return value == null ? null : new BigDecimal(value).divide(new BigDecimal(100));
        }

        @TypeConverter
        public Long toLong(BigDecimal bigDecimal) {
            if (bigDecimal == null) {
                return null;
            } else {
                return bigDecimal.multiply(new BigDecimal(100)).longValue();
            }
        }
    }
kx1ctssn

kx1ctssn3#

@ip696您可以尝试将BigDecimal转换为Double,而不是将BigDecimal转换为String

@TypeConverter
fun amountToDouble(input: BigDecimal?): Double? {
    return input?.toDouble()
}

@TypeConverter
fun fromDouble(input: Double?): BigDecimal? {
    return input?.toBigDecimal()
}

那么下面的代码将工作。

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

补充说明:ORDER BY子句也将按预期工作。

相关问题