Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » a custom number class
a custom number class [message #382753] Mon, 20 October 2008 11:51 Go to next message
Tom Eugelink is currently offline Tom EugelinkFriend
Messages: 807
Registered: July 2009
Senior Member
Ok, I know this is very "on the edge", but I'm almost there. So close...

I'm using jGoodies binding library, and one of the properties in my BM got an update because "0.00" is not equal to "0". But because that property has a restriction on when an update is allowed, an IllegalArgumentException was thrown. The problem naturally is that the update should not have occurred: the value was 0 and remained 0.
Now I understand that "0.00" and "0" are not equal, taking the scale into account, but I got frustrated have to yet-again deal with these scale and rounding nuances, so I decided to try and roll-in an experimental Number class I've written some time ago called "AnyNumber"

AnyNumber does away with rounding, because it stores every number as a division. So 0,3333333 is stored as "1 divided by 3". Like BigDecimal I added all the required mathematical methods like add, subtract, multiply, power, abs, sgn, etc, etc. AnyNumber uses BigInteger for its internal storage, so it can become very big, and naturally it is optimized when the divider is ONE.
It also implements the Number interface and has conversions from and to the regular numeric types.

First step I took is to add a converter class to the BM, allowing the reading and writing from regular database numbers. I needed some tweaks in the Swing environment to spit out the correct class, but as a whole it is up and running within a working day.

Load, persist, searching, everything works just fine! My screens all work, and my scale problem went away like snow in the Sahara. So all is peachy except one thing: sorting. When I try to sort in a AnyNumber field, I get an error message:
"invalid ORDER BY item [t.iVersion] of type [org.tbee.math.AnyNumber], expected expresion of an orderable type"

Is there anyway to make sorting on these custom items possible?
Maybe the Converter interface could be extended with a method to provide the information to enable sorting on @Convert fields?

It would be a shame to fail over this, after all the rest fell into place.

Tom
Re: a custom number class [message #382755 is a reply to message #382753] Mon, 20 October 2008 12:01 Go to previous messageGo to next message
Tom Eugelink is currently offline Tom EugelinkFriend
Messages: 807
Registered: July 2009
Senior Member
I used Collections.sort to removed the order by in the query, so I can work around it. But still...
Re: a custom number class [message #382758 is a reply to message #382753] Mon, 20 October 2008 13:28 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

The error doesn't sound like a typical EclipseLink error message, could
you include the full exception message and stack trace. Also what query
do you execute to get it?

--
James
http://www.nabble.com/EclipseLink---Users-f26658.html


James : Wiki : Book : Blog : Twitter
Re: a custom number class [message #382760 is a reply to message #382758] Mon, 20 October 2008 14:25 Go to previous messageGo to next message
Tom Eugelink is currently offline Tom EugelinkFriend
Messages: 807
Registered: July 2009
Senior Member
> The error doesn't sound like a typical EclipseLink error message, could
> you include the full exception message and stack trace. Also what query
> do you execute to get it?


Exception in thread "main" java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.creat eQuery(EntityManagerImpl.java:742)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAcce ssorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMe thodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.tbee.util.jpa.EntityManagerExtender.invoke(EntityManager Extender.java:101)
at $Proxy32.createQuery(Unknown Source)
at nl.reinders.bm.Standversion.findAllOrderedByStandIdAndVersio n(Standversion.java:205)
at nl.reinders.bm.BMTestToplink.main(BMTestToplink.java:47)
Caused by: Exception [EclipseLink-8021] (Eclipse Persistence Services - 1.0.1 (Build 1.0 - 20080827)): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Error compiling the query [select t from Standversion t join fetch t.iStand order by t.iStand.iStandid, t.iVersion], line 1, column 78: invalid ORDER BY item [t.iVersion] of type [org.tbee.math.AnyNumber], expected expression of an orderable type.
at org.eclipse.persistence.exceptions.JPQLException.expectedOrd erableOrderByItem(JPQLException.java:335)
at org.eclipse.persistence.internal.jpa.parsing.OrderByItemNode .validate(OrderByItemNode.java:43)
at org.eclipse.persistence.internal.jpa.parsing.OrderByNode.val idate(OrderByNode.java:72)
at org.eclipse.persistence.internal.jpa.parsing.ParseTree.valid ate(ParseTree.java:214)
at org.eclipse.persistence.internal.jpa.parsing.ParseTree.valid ate(ParseTree.java:187)
at org.eclipse.persistence.internal.jpa.parsing.ParseTree.valid ate(ParseTree.java:177)2008-10-20 16:22:11,252 INFO org.tbee.util.jpa.EntityManagerExtender.invoke(EntityManager Extender.java:169) createQuery: java.lang.reflect.InvocationTargetException->java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager

at org.eclipse.persistence.internal.jpa.parsing.JPQLParseTree.p opulateReadQueryInternal(JPQLParseTree.java:110)
at org.eclipse.persistence.internal.jpa.parsing.JPQLParseTree.p opulateQuery(JPQLParseTree.java:84)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQL DatabaseQuery(EJBQueryImpl.java:207)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQL DatabaseQuery(EJBQueryImpl.java:170)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQL DatabaseQuery(EJBQueryImpl.java:134)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:95)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:80)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.creat eQuery(EntityManagerImpl.java:740)
... 8 more


The code:
Query lQuery = lEntityManager.createQuery("select t from Standversion t join fetch t.iStand order by t.iStand.iStandid, t.iVersion");
java.util.List<nl.reinders.bm.Standversion> lList = lQuery.getResultList();
return lList;

The Entity:

@Column(name="version", nullable=false)
@Convert("AnyNumberConverter")
volatile private org.tbee.math.AnyNumber iVersion = null;
Re: a custom number class [message #382761 is a reply to message #382758] Mon, 20 October 2008 14:42 Go to previous messageGo to next message
Tom Eugelink is currently offline Tom EugelinkFriend
Messages: 807
Registered: July 2009
Senior Member
Please note that I ran into one other snag for which I haven't found a good solution to yet: storage in the database. In order to maintain accuracy (1/3 instead of 0.33333...) I need to store the string representation "1/3" instead of the decimal presentation in the database. If I store the decimal notation, I introduce an inaccuracy when the entities are read back. This means however that the value in the database will become practically unusable for SQL.

The only other way to correctly store the AnyNumbers, is storing boths values in separate integer fields, AFAIK this is possible using embedded classes instead of converters in EclipseLink. SQL can then do a "a/b" each time it needs the value, but that would mean a big change to the datamodel and all views and queries.

For this BM that is too much work, however the approach is usable if I start a new database for a new project (which I may soon).

It still is an interesting experiment to see if it is possible to keep rounding out of the code until the last moment (presenting the value to the user). So I may switch approach.

Tom
Re: a custom number class [message #382765 is a reply to message #382760] Tue, 21 October 2008 13:05 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

Please log a bug for this, we should not be doing such validation.
Include the exception stack trace.

BTW your AnyNumber class was called Fraction in the old Smalltalk days.
Possibly you could store it in the database as a long using the high int
for the numerator and the low int for the denominator, perhaps as a string
as well, but in general unless your writing some mathematical application
it is probably not worth the trouble.


James : Wiki : Book : Blog : Twitter
Re: a custom number class [message #382767 is a reply to message #382765] Tue, 21 October 2008 13:57 Go to previous messageGo to next message
Tom Eugelink is currently offline Tom EugelinkFriend
Messages: 807
Registered: July 2009
Senior Member
> Please log a bug for this, we should not be doing such validation.
> Include the exception stack trace.

Bug#: 251533


> BTW your AnyNumber class was called Fraction in the old Smalltalk days.

Interesting. The pureness of Smalltalk always is impressive. Maybe I should rename my class :-)
FYI my class name was derived from the fact that the Java number classes cannot store all numbers, like 1/3 cannot be correctly written in the decimal system, there are also numbers that cannot be correctly written in the binary system.


> Possibly you could store it in the database as a long using the high int
> for the numerator and the low int for the denominator, perhaps as a
> string as well, but in general unless your writing some mathematical
> application it is probably not worth the trouble.

Maybe. The production solution to the problem involved patching the scale of the BigDecimal and is already up and running.

But I do get frequently frustrated by all the scale and rounding issues that one has to cope with, just for doing some simple calculating, even in financial applications. Back in the days of school things were simple; 1/3 was 1/3, not 0.33 or 0.3 or 0. AnyNumber does take away all those worries, so it certainly makes other areas less complex. But database storage still doesn't have a nice solution.

Another possible approach would be to only use it during calculations. I mean, the price of an item is rounded anyhow, and so are the amounts (in the end some human has to pick that order), and that is the input for any calculation. The output must be a payable amount, so is also rounded (ever tried to type 0.33333333333333 in your banking application?).
IOW if AnyNumber can easily use the other numbers, it still is an interesting class to use for calculation. That is what I'll be trying in the production BM.
Re: a custom number class [message #382772 is a reply to message #382765] Wed, 22 October 2008 08:10 Go to previous message
Tom Eugelink is currently offline Tom EugelinkFriend
Messages: 807
Registered: July 2009
Senior Member
> but in general unless your writing some mathematical
> application it is probably not worth the trouble.

Hm, even though storing it as a regular decimal removes the accuracy, it still is one-class-fits-all numbers. You don't have to alternate between Integer, Double, BigInteger, BigDecimal... So it does make life easier.
Previous Topic:QueryRedirector problem (Bug/JPA)
Next Topic:Persistent Java Class Data Base Storage?
Goto Forum:
  


Current Time: Mon Dec 22 11:30:48 GMT 2014

Powered by FUDForum. Page generated in 0.01745 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software