【问题标题】:How can I store currency in ROOM DB?如何在 ROOM DB 中存储货币?
【发布时间】:2017-12-05 10:48:39
【问题描述】:

我有实体:

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

    @PrimaryKey(autoGenerate = true)
    private Long id;

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

我需要将它存储在 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();
            }
        }
    }

并添加到列:

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

现在我将货币存储在双列中。我想要 summ totalcurrency 的方法:

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

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

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

LiveData<BigDecimal> totalSum();

【问题讨论】:

    标签: android android-room


    【解决方案1】:

    我在 StringBigDecimal 之间使用,而不是 LongBigDecimal 转换器。

    警告:通过这种方式,您不能在 Room DB 中使用 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 中检索SUM, TOTAL,...:

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

    希望对您有所帮助!

    【讨论】:

      【解决方案2】:

      您可以长期存储您的价值。如果你有例如。 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();
                  }
              }
          }
      

      【讨论】:

      • 我喜欢这个解决方案,但不幸的是,它没有考虑货币中小数位数不同的国家/地区。请参阅此 Stack Overflow 问题(忽略与 iPhone 开发有关的事实):(stackoverflow.com/questions/2701301/…)
      猜你喜欢
      • 2022-08-19
      • 1970-01-01
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多