This blog has moved to
http://blog.matthias-reining.com

Die bestehenden Artikel bleiben vorerst alle bei blogspot. Neue Artikel veröffentliche ich allerdings nur noch auf http://blog.matthias-reining.com

Mittwoch, 25. März 2009

JPA, Sequenzen (non-Id) und Oracle

Eine Sequenz per JPA abzufragen ist bekanntermaßen nicht so einfach – JPA 1.0 unterstützt nur Sequenzen bei der Genierung von IDs (@Id, @GeneratedValue). Eine Möglichkeit einen eindeutigen Wert trotzdem aus einer Sequenz zu bekommen ist natürlich per JPA Native Query (siehe bspw. http://stackoverflow.com/questions/277630/hibernate-jpa-sequence-non-id )

Nach kurzem googlen bekommt hier jede Menge Treffer die etwa wie folgt aussehen (für eine Oracle Sequenz):

Query query = em.createNativeQuery("select seq.nextval from dual ");
long nextNumber = new Long(((Number) query.getSingleResult()).longValue());

Leider funktioniert dies nicht (zumindest bei mir… L )

Es kommt hier immer die Fehlermeldung: ORA-00287: Sequence-Nummer hier nicht zulässig

Der Grund hierfür liegt daran, dass Hibernate (JPA unter JBoss), aus dem getSingleResult folgendes Statement baut:

select * from ( select profilenumber.nextval from dual ) where rownum <= 1 

Und dies ist leider kein korrektes SQL Statement, da hier eine Sequenz in der WHERE Klausel vorkommt…

Mit folgendem Java Code erhält man das gewünschte Ergebnis:

Query query = em.createNativeQuery("select seq.nextval from dual ");
long nextNumber = Long.valueOf(query.getResultList().get(0).toString());

Hier wird die überflüssige Select-Klammer um die eigentliche Sequenzabfrage in SQL weggelassen.


 

3 Kommentare:

  1. Methode zur NextVal from SEQ funktioniert nicht...
    Exception in thread "main" java.lang.NumberFormatException: For input string: "[220120327]"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Long.parseLong(Long.java:403)
    at java.lang.Long.parseLong(Long.java:461)
    at com.becker.struts.database.PersistenceManager.nextAccountNumber(PersistenceManager.java:69)
    at com.becker.struts.account.AccountHandler.createAccount(AccountHandler.java:28)
    at com.becker.struts.database.Test.main(Test.java:17)

    AntwortenLöschen
  2. select seq.nextval from dual

    seq ist natürlich der Sequenz Name.
    Die Sequenz muss hier natürlich manuell in Oracle angelegt werden. Die Funktionsweise des Statements kann relativ einfach bspw. mit PL/SQL Developer oder einfach auf der Konsole mit sqlplus geprüft werden.

    AntwortenLöschen
  3. Hallo,

    Ich danke dir! Hat super funktioniert. Das "getSingleResulT()" hat mich schon wahnsinnig gemacht :D

    Greetz
    Q

    AntwortenLöschen