Java: Rounding error from Double to BigDecimal

Today’s amusement in my job:

Rounding error from Double to BigDecimal, see java docs for public BigDecimal(double val).

Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625

 

Workaround 1: Convert Double to String before converting to BigDecimal, as suggested in the java docs for BigDecimal

BigDecimal b = new BigDecimal(Double.toString(double));

 

Workaround 2: Round!
Double d = ...; // your (rounded) value
BigDecimal b = new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP);

.

Another problem with Double in Java: http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/

SQL – Drop constraint without specifying its name

Drop a UNIQUE constraint in relational databases like Oracle without specifying its name by referencing the column or columns:

ALTER TABLE Employee DROP UNIQUE (name)

.

But if you want to drop a NOT NULL constraint  without specifying its name you have to use a workaround, if there is an index on the column:

ALTER TABLE Employee ADD (name_ varchar(32));
update Employee set name_ = name;
ALTER TABLE Employee DROP COLUMN name;
ALTER TABLE Employee ADD (name varchar(32));
update Employee set name = name_;
ALTER TABLE Employee DROP COLUMN name_;

.

To drop a NOT NULL constraint in Oracle you can MODIFY an unindexed column:

ALTER TABLE Employee MODIFY name NULL;

.

ps. Dieses Mal ein How-To-Posting aus meinem spannenden Leben als Software-Entwicklerin in Englisch, zum leichteren Wiederfinden in Suchmaschinen.

Multiple writable mappings in Java Persistence API

Seit kurzem setzte ich mich mit der Java Persistence API auseinander, das mit Hibernate und dem von uns eingesetzten Oracle Toplink implementiert wurde.

Folgende Fehlermeldung beschäftigte mich bei einer OneToMany-Relation

Multiple writable mappings exist for the field [tabltenname.spaltenname]. Only one may be defined as writable, all others must be specified read-only.

Die Lösung war das explizite deklarieren der Spalte als “read only”, was man mit den Optionen nullable=false, insertable=false und updatable=false bei der @Column-Annotation erreicht.

Spannend, nicht? ;)

java-coffee-cup-300x219

oracle update mit inner join

wieder mal ein kleines howto, für etwas, das mir wieder mal auf die schnelle nicht eingefallen ist.

wenn man in einer tabelle A alle spalten a auf einen bestimmten wert setzen möchte, die eine bestimmte bedingung (A.b = B.b) mit einer anderen tabelle B erfüllen, geht das in oracle so:

UPDATE A
set A.a =
(SELECT B.a
FROM B
WHERE A.b = B.b)

in access würde es so gehen:

update A inner join B on
A.b = B.b
SET A.a = B.a

in SQL server so:
UPDATE A
SET A.a = B.a
INNER JOIN B
ON A.b = B.b

siehe z.b. auch sql-tutorial

convert date to calendar in java

heute wieder mal googlen müssen, weils mir wieder mal entfallen ist, deswegen gleich ein beitrag für die howto section.

in java sind die alten, sehr hilfreichen funktionen von java.util.Date, die teile des datums zurückgeben, wie date.getMonth(), leider depricated, und zwar schon seit v. 1.1. stattdessen wird heute java.util.Calendar verwendet. …und das geht so ;)

Date date = .. // das datum, das man aufsplitten will;
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// monat fängt mit 0 an!
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DAY_OF_MONTH);
int year = cal.get(Calendar.YEAR);

beim suchen hab ich eine hilfreiche seite gefunden mit vielen tutorials und beispielen gefunden.

.

wer ein formatiertes datum braucht, nimmt am besten:


Date date = new Date();
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat( "yyyyMMdd" );

oracle group concat

oft habe ich mir schon die frage gestellt, wie der einfachste weg ist, mehrere strings, die aus einem SQL statement in mehreren rows kommen, zu einem string in einer row zusammenzufassen. im mysql gibt es die funktion group_concat(), die in oracle aber leider nicht vorkommt.

das problem im detail ist, dass das statement für ein dataset:

select
   'A' as text
from
   dual
union
select
   'B' as text
from
   dual

folgendes liefert:

text

A
B

…, man aber manchmal den text in einem einzigen string in einer row und nicht in mehreren rows zurückbekommen will, also “A B”

die lösung dafür ist entweder mit plsql prozeduren zu arbeiten (was ich bis jetzt immer gemacht habe) oder auf hierarchische statements zurückzugreifen. folgendes knappes statement liefert die lösung

select
   ltrim(max(sys_connect_by_path(text, ' ')), ' ')
from
(
   select
      text,
      rownum as rn
   from
   (
      // dataset, z.b. siehe oben
   )
)
start with rn = 1
connect by prior rn=rn-1

eine etwas komplexere lösung ist im tom kyte blog zu finden

XSQL treibt mich in den wahnsinn

mal wieder was aus meinem spannenden alltag als software-entwickler:

Oracle XSQL Servlet gibt so nette fehlermeldungen aus wie “Ungültiger Spaltenindex“, die aber irgendwie nicht direkt mit dem Index, der Anzahl oder Reihenfolge der Spalten des SQL statements oder ähnlichem zu tun hatte…

die lösung des problems war aber bald geklärt, da ich mit hilfe eines lieben arbeitskollegen erkannte, dass die anzahl der bind-params nicht mit der anzahl der verwendeten params übereinstimmt.

in xsql müssen alle params, die mit dem <xsql:query .. />-tag bind-params übergeben werden verwendet werden. diese können mit einem fragezeichen ? oder direkt mit dem prefix “:” angesprochen werden, aber nicht zu wenige, keine doppelten verwendungen und nicht zu viele… eben genau richtig passend muss es sein. das ist die banale lösung.

.

wieso können programmierer dieser tools nicht vernünftige fehlermeldungen ausgeben? sowas wie “Anzahl der bind-params stimmt nicht mit der Anzahl der verwendeten Params überein”. da wär ich und wahrscheinlich alle xsql progger sehr glücklich. ein anderes beispiel für grauenhafte fehlermeldungen sind die gute, alte NullPointerException in Java oder “undefined is not a function” in helma ;)

.

nachtrag: die selbe lösung gibt es auch bei dr fehlermeldung “fehlender IN- oder OUT-Parameter auf Index:: i“. hier wird ein parameter, der mit bind-params gesetzt wird, öfter im SQL verwendet, als er definiert wurde. die lösung: den parameter sooft in bind-params übergeben, wie er verwendet wird!

torque throws ORA-01424 – purge the recycle bin

schon wieder passiert und wieder mal länger nach der lösung gesucht, bis es mir wieder (spät, aber doch) eingefallen ist:

wird eine ORA-01424 oracle fehlermeldung beim generieren der java-klassen aus der DB über die torque geworfen, hat man wohl wieder das magische wort purge beim löschen der tabellen vergessen.

drop table drop_me purge
/

der fehler tritt auf, da die tabellen nicht vollständig gelöscht wurden und somit im recycle bin der DB liegen. purge bereinigt den papierkorb, bzw wird beim drop einer tabelle diese gleich vollständig gelöscht.

der fehler ORA-01424 deutet eigentlich auf ein fehlendes zeichen nach dem escape character hin und führt in diesem zusammenhang leider nur in eine falsche richtung.

howto: einkommensteuererklärung mit kennzahlen für 2007 mit pauschalierung

und jährlich grüßt das murmeltier… da ich mich jedes jahr aufs neue frag, in welches feld des formulars für die ESt wieder mal genau was eingetragen werden soll, hab ich dieses mal eine anleitung geschrieben.

howto für eine einkommensteuererklärung für 2007 für eine basispauschalierung mit 12%:

Gewinnermittlungsart: Basispauschalierung gemäß § 17 Abs. 1
USt-Bruttosystem
Branchenkennzahl lt. Beilage E 2: Softwareberatung und -entwicklung

posten summe kennzahl anmerkung
einnahmen 2007, ohne ust x 9040
ust der einnahmen x*0,2 9093
pauschale x*0,12 9230 summe von pauschale und sva in 9230 eintragen
summe der 2007 bezahlten sva-beiträge y 9230 summe von pauschale und sva in 9230 eintragen
ust, nochmal x*0,2 9233
Einkünfte aus selbständiger Arbeit x-x*0,12-y 320 einnahmen – ausgaben
sonderausgaben z 455 Versicherungsprämien z.b. private pensionsversicherung, es wird nur ein viertel abgesetzt
Außergewöhnliche Belastungen w 730 Krankheitskosten z.b. arztrechnungen, medikamente
.. was sonst noch anfällt

natürlich ohne gewähr! falls sich fehler eingeschlichen haben, bitte sofort melden.

nachtrag: einen guten leitfaden gibts bei der wko.

man kann neben der pauschale auch

  • ausgaben für handelswaren
  • lohnaufwand und fremdlöhne
  • die bereits erwähnten gewerbliche SVA-beiträge und bezahlte USt
  • steuerberatungskosten (als sonderausgaben)

absetzen

ich empfehle thomapyrin für die nachzahlung ;)