Using Realm.io to store money values

心已入冬 提交于 2019-12-01 18:09:59

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.

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.

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

Dante

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!