Sunday, June 20, 2010

Be warn, The BigDecimal stripTrailingZeros method could have you fired.

Not enough people are aware of the flaws of the oracle jdbc driver when using java 5 and BigDecimal (bug# 5527479 and it is fixed in 10.2.0.4). You can see a full example on this thread of the javalobby forums. If you never heard about this bug and you're using an older version of the oracle driver (before 1.2.0.4), you should really follow the link above.

To resume, when instantiating a BigDecimal using its non String constructor, sometimes the driver makes a bad interpretation and insert a bad value in the database. Imagine my surprise, since I'm working on a trading application, when I ran across it. A client bought 2250 shares of a certain company and got only 22 shares. We only saw this the day after when our client complains. Oups...

The solution I found was quite simple. We just have to use the String constructor of the BigDecimal. OK.

The thing I didn't understand was that I always created my BigDecimal objects using the String constructor. So I should not have run into that bug.

My mistake was to use the stripTrailingZeros method right after I created my BigDecimal objects. This method returns a new Bigdecimal using the BigInteger/scale constructor stripped from its trailing zeros.

If you really want to use this method and you cannot upgrade your driver (10.2.0.4 has some issues too), a simple solution is to re-create a new BigDecimal object after calling stripTrailingZeros like this :
BigDecimal myNumber = new BigDecimal("2250.0");
myNumber = myNumber.stripTrailingZeros();
myNumber = new BigDecimal(myNumber.toPlainString());
If you're using iBatis, you can use the solution described here.