3

We are generating our jpa access layers with MyEclipse. Afterwards we have the generated models and data layer access services. We ran into some problems for some fields with a defined precision.

Entity:

@Entity
public class TestEntity{
   @Column(name="DECTEST", scale = 3, precision = 13)
   BigDecimal decTest;

}

Now we create a bean and try to save it:

TestEntity te = new TestEntity();
te.setDecTest(new BigDecimal(1.2));

TestEntityService.save(te);

We get the following error: Caused by: com.ibm.db2.jcc.c.SqlException: [ibm][db2][jcc][t4][1037][11190] Exception occurred during BigDecimal conversion. See attached Throwable for details.

Caused by: com.ibm.db2.jcc.a.a: [ibm][db2][jcc][converters][608][10994] Overflow occurred during numeric data type conversion of "1.1999999999999999555910790149937383830547332763671875".
at com.ibm.db2.jcc.a.e.a(e.java:61)
at com.ibm.db2.jcc.b.jb.a(jb.java:1772)
... 73 more

The problem seems to be that our BigDecimals scale is higher then the one from the database.

A working workaround is:

TestEntity te = new TestEntity();

BigDecimal decTest = new BigDecimal(1.2);

te.setDecTest(decTest.setScale(3,RoundingMode.HALF_UP);

TestEntityService.save(te);

With this workaround we reduce the BigDecimals precicsion manually to the one of the database.

However if the data model changes we would have to adjust the scale there manually. Is there a way to get our jpa / hibernate implementation to do that conversion for us automatically? E.g. with setting a property. Doing it at the spot where one is creating the bean would be the wrong spot to do it anyways.

Udo Held
  • 12,314
  • 11
  • 67
  • 93

1 Answers1

8

You could use a custom user type, or you could simply implement the setter of the property like this:

public void setDecTest(BigDecimal decTest) {
    this.decTest = decTest.setScale(3, RoundingMode.HALF_UP));
}

This rounding would thus be encapsulated in the entity.

Note that using a double to initialize a BigDecimal is a bit strange. If you want 1.2 to be stored in the BigDecimal, use new BigDecimal("1.2"), and you won't have a BigDecimal initialized with 1.1999999999999999555910790149937383830547332763671875.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thought about those two as well. However the 1.2 was for testing only. Its coming from the UI and should be validated as a number so that noone can send down "hallo" instead of a number. As the access layer is generated I don't want to modify it. Using several BigDecimal properties the manual way isn't nice, however if nothing better comes up, we probably have to go for it. – Udo Held Aug 10 '12 at 10:09
  • 1
    You saved me some hassle with your comment about not parsing double to the constructor of BigDecimal. it was a temptation that i needed to say no to. – Nicholas DiPiazza Jun 09 '13 at 20:51