Using Realm.io to store money values

前端 未结 4 1457
被撕碎了的回忆
被撕碎了的回忆 2021-01-18 09:11

I\'m starting to play with Realm.io in an Android app that I\'m writing. In one of my data objects, I\'m required to store a currency value. Previously I had stored the valu

相关标签:
4条回答
  • 2021-01-18 09:37

    Emanuele from Realm here.

    You are right, using floats or doubles for currency is a bad idea.

    We don't support BigDecimal for now, and before we do we will have to see how that plays in relation to all other language bindings since we want realm files to be compatible across all the supported platforms.

    Christian's idea is good, but I see the conversion to and from String to be a bit slow. If you don't need the arbitrary precision property of BigDecimal you could use long and multiply/divide by the factor your required precision calls for. This would also save a lot of space in terms of the size of the Realm file since integer values are bit packed.

    0 讨论(0)
  • 2021-01-18 09:51

    What I do is store it as long

    I have defined in my application a constant like so:

    public static final BigDecimal MONEY_PRECISION = new BigDecimal(1000);
    

    and when I need to store a big decimal it goes like this:

    public class MoneyClass extends RealmObject {
        long _price = 0;
    
        public void set_price(BigDecimal price) {
            this._price = price.longValue() * App.MONEY_PRECISION.longValue();
        }
    
        public BigDecimal get_price() {
           return new BigDecimal(_price).divide(App.MONEY_PRECISION, 0, 0);
        }
    
    }
    

    In theory this should be faster than saving it on strings , but I haven't really looked at the realm code much

    0 讨论(0)
  • 2021-01-18 09:52

    My solution:

    Define Interface:

    public interface RealmConvert {
       void convertToDB();
    
       void convertToObj();
    }
    

    Define Entity:

    @Ignore
    private BigDecimal balance;
    private String balanceStr;
    
    @Override public void convertToDB() {
      if (getBalance() != null) {
        setBalanceStr(getBalance().toString());
      }
    }
    
    @Override public void convertToObj() {
      if (getBalanceStr() != null) {
        setBalance(new BigDecimal(getBalanceStr()));
      }
    }
    

    Before you copyToRealm:call method convertToDB

    When you need to use the entity: call method convert obj

    It's not an elegant solution, but it works.

    Christian Melchior's answer doesn't work in my app.

    0 讨论(0)
  • 2021-01-18 09:57

    That could work, but would probably be suboptimal if do calculations on your current BigDecimal objects.

    You could also use the @Ignore annotation to provide a wrapper method for your custom objects like this:

    public class Money extends RealmObject {
    
      private String dbValue;
      @Ignore private BigDecimal value;
    
      public String getDbValue() {
          return dbValue;
      }
    
      public void setDbValue(String dbValue) {
          this.dbValue = dbValue;
      }
    
      public BigDecimal getValue() {
         return new BigDecimal(getDbValue());
      }
    
      public void setValue(BigDecimal value) {
          setDbValue(value.toString());
      }
    }
    

    It is not perfect as you need to expose the *dbValue() methods, but it should work.

    I would also suggest going to https://github.com/realm/realm-java/issues and make a feature request for this as BigDecimal is probably one of those java classes used by so many that it could warrant native Realm support, just like Date has.

    0 讨论(0)
提交回复
热议问题