如何在ROOM DB中存储货币?

ip6*_*696 5 android android-room

我有实体:

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

    @PrimaryKey(autoGenerate = true)
    private Long id;

    @ColumnInfo(name = "amount")
    private BigDecimal amount;
Run Code Online (Sandbox Code Playgroud)

我需要将其存储在Room DB中。我无法存储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();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

并添加到列:

@TypeConverters(Converters.class)
    @ColumnInfo(name = "amount")
    private BigDecimal amount;
Run Code Online (Sandbox Code Playgroud)

现在,我将货币存储在双列中。我想要求和summarycurrency的方法:

@Query("SELECT SUM(amount) FROM products")
LiveData<Double> totalSum();
Run Code Online (Sandbox Code Playgroud)

但是我认为这是一种不好的方法,因为转换时我可能会丢失一些值。

我的问题:如何在ROOM DB中保存货币?和返回方法

LiveData<BigDecimal> totalSum();
Run Code Online (Sandbox Code Playgroud)

Fil*_* P. 8

您可以长期存储您的价值。如果你有例如。1.55 序列化时乘以 100 并将 long 存储在 db 中。当您反序列化时,从这个长度创建 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();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个解决方案,但不幸的是,它没有考虑到在其货币中具有不同小数位数的国家。请参阅此堆栈溢出问题(忽略与 iPhone 开发有关的事实):(/sf/ask/189091101/) (2认同)

dph*_*ans 6

我使用的是 between和,而不是LongvsBigDecimal转换器。StringBigDecimal

警告:通过这种方式,您不能在 Room DB 中使用SUM,TOTAL或其他表达式。因为我的应用程序的目的是使用多种货币,所以我手动检索数据并根据当前汇率进行计算。

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

}
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)

所以你可以从 Dao 中检索SUM, TOTAL,... :

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

希望有帮助!

  • 在您使用 double 的第二个解决方案中,它是否保留了数字的精确数量?我的意思是许多最佳实践禁止使用“Double”作为货币类型,因为它没有小数,而是有二进制分数。 (3认同)