iBatis Migration von MySQL

Helios co.

Lt. Commander
Registriert
März 2005
Beiträge
1.863
Hallo @all,

ich migriere gerade eine größere Anwendung die in Java geschrieben ist und als Db mysql verwendet. Das ganze soll nun nach Oracle migriert werden.

Die Persistenz übernimmt iBatis. Ich muss an dieser Stelle direkt anmerken, dass ich mich nicht mit iBatis gut auskenne.

Das größte Problem stellt bei der Migration die LIMIT Funktion von MySQL dar.

Beispielsweise sei die folgende Query gegeben:

Code:
<select id="getPendingUserByActivationCode" resultMap="UserCommon.userWithActivationCode" parameterClass="userParam">
		SELECT <include refid="commonUserAttributes"/>, activation_code
		FROM pendingUser 
		LEFT JOIN ldapUser USING (user_name) 
		WHERE spammer = 0 
		AND activation_code = #rawSearch#
		LIMIT #limit# OFFSET #offset#
	</select>


Ich habe bereits viele varianten ausprobiert diese Query zu migrieren, leider bis jetzt stets ohne Erfolg, wobei die Ursache für das Versagen bei iBatis zu finden ist.

1. Ich kann die Queriy nicht mittels PLSQL migrieren
2. Es klappt auch nicht die Query mittels ROWNUMBER zu migrieren, zumindest nichz ohne Weiteres. Denn scheinbar gibt es Probleme mit den Inline Parametern #limit# und #offset#.


Code:
<select id="getPendingUserByActivationCode" resultMap="UserCommon.userWithActivationCode" parameterClass="userParam">
    SELECT user_name, user_email, user_homepage, user_realname, user_password,
        api_key, birthday, gender, hobbies, interests, ip_address, openurl, place, profession,
        reg_date, spammer, role_, updated_by, updated_at, to_classify, tmp_password, tmp_request_date,
        ldapUserId, lastAccess, activation_code
    FROM
    (SELECT t.*, ROWNUM r
      FROM
      (SELECT <include refid="commonUserAttributes"/>, activation_code
            FROM pendingUser
            LEFT JOIN ldapUser USING (user_name)
            WHERE spammer = 0
            AND activation_code = #rawSearch#) t
      WHERE ROWNUM &lt; (#limit# + #offset#))
    WHERE r &gt; #offset#
</select>

Relevant ist die folegdne Zeile:
Code:
WHERE ROWNUM &lt; (#limit# + #offset#)

Dieser Ansatz geht nicht, und ich kriege einen Inline Parameter Fehler.
Folgendes geht:

Code:
WHERE ROWNUM &lt; (#limit#)
liefert aber natürlich natürlich nicht das Verhalten, das es soll!

Da scheinbar iBatis Probleme mit der Addition von Parametern hat, habe ich einen sehr primitiven Ansatz implementiert:

Code:
WHERE ROWNUM &lt; (select wert from mylimit2 where limit = #limit# and offset = #offset#))

Dabei enthält die Tabelle mylimit2 mappings, der Art

Code:
offset | limit | wert (= limit+offset)

Aber auch das klappt nicht, wobei mir nicht klar ist warum. Ohne iBatis klappt diese Query einwandfrei, also muss ich davon ausgehen, dass hier ein Problem mit den Parametern vorliegen, bzw. mit deren Verwendung.

Unter mySQL funktioniert natürlich alles (also die Originalquery) korrekt!

Wie gesagt, ich habe nur wenig Ahnung von iBatis, daher die Frage: Kann mir jemand wenisgetns erklären warum das so nicht funktioniert?

Bin wirklich dankbar für jeden Rat!
 
Zuletzt bearbeitet:
wie immer erst mal eine allgemein Ansprache,
ich find es komisch, dass so was unprofessionell gemacht wird
schließlich habt ihr kein mehr gewinn wenn ihr auf Oracle umsteigt
aber dessen Fähigkeiten nicht nutzen könnt.

nun zum Problem dein letzten Ansatz finde ich gut nur die Umsetzung würde ich
anders versuchen:
Code:
Alt : WHERE ROWNUM &lt; (select wert from mylimit2 where limit = #limit# and offset = #offset#))
Neu: WHERE ROWNUM &lt; (select #offset# + #limit# from dual ))
 
ich find es komisch, dass so was unprofessionell gemacht wird
schließlich habt ihr kein mehr gewinn wenn ihr auf Oracle umsteigt

Doch genau den haben wir. Schon alleine weil wir die Möglichkeit haben die komplette Datenbank im RAM laufen zu lassen. Mir wäre neu, dass das mit MySQL geht, und selbst wenn es damit gehen würde, ist meine Vorgabe das Ding auf Oracle zu migrieren.

Zudem ist das ganze ein Forschungsprojekt :)

Bei sehr komplexen Anfragen liegt Oracle was die Performance anbetrifft eh deutlich vorne.

Aber egal, letztlich soll das hier keine Religionsfrage werden ;)



Was deinen Vorschlag anbetrifft, und vielen Dank für diesen!
Code:
Alt : WHERE ROWNUM &lt; (select wert from mylimit2 where limit = #limit# and offset = #offset#))
Neu: WHERE ROWNUM &lt; (select #offset# + #limit# from dual ))

Das ändert leider nichts an meinem grundlegenden Problem.
Aus irgendeinem Grund wird #limit# nicht korrekt gesetzt, was auch erklärt, warum es weder mittels PLSQL Funktion noch mittels ganz plumpen Workaround geklappt hat.

Scheinbar ist bei mir limit stets 0. Wenn ich nun zwischen > 0 und < 0 (ROWNUM) eine Zeile haben will, kommt natürlich nicht viel zurück, also schlägt die Query auch fehl.

Ich muss nur noch herausfinden warum das bei MySQL funzt und bei Oracle nicht. Das macht eigentlich keinen Sinn (für mich).
 
ich hab mich noch nie mit ibatis beschätig und werde das auch nicht machen,
aber vielleicht erkennt er das es oracle ist und kennt daher kein limit
weil es in oracle sowas nicht gibt.

wie groß offset und limit ist kannst du dir doch in ein select doch spasses halber ausgeben
nimm irgend eine select und füg dort 2 spalten hinzu
Code:
select ... ,#offset# "Offset",  #limit# "Limit" from ...

vielleicht liegt auch ein schreib fehler vor und das limit heisst anders
 
ich hab mich noch nie mit ibatis beschätig und werde das auch nicht machen
Ja, schön wäre es wenn ich das von mir auch behaupten könnte :)

Bei größeren Anwendungen führt aber nichts mehr dran vorbei. D.h. wenn du eine Anwendung im Team entwickelst und die Anwendung sagen wir mal 1 Million Zeilen und mindestens 500 Queries hat, wird es schwer nur mit JDBC Mitteln zu arbeiten, und die Queries direkt im Code zu bunkern.

ausgeben
nimm irgend eine select und füg dort 2 spalten hinzu

Das ist eine gute Idee! Ich fürchte nur, dass das nicht so einfach gehen wird. Die Application läuft mittels Maven und Spring auf einem Tomcat. Hier sich etwas einfach mal ausgeben zu lassen ist alles andere als trivial.

Selbst simple Fehlermeldungen muss ich mittels log4j ausgeben lassen. Und selbst das funzt oft nicht so wie ich es mir wünsche!

vielleicht liegt auch ein schreib fehler vor und das limit heisst anders
Das auf keinen Fall. Was ich mir auch schon gedacht habe: limit ist ein reserviertes Wort von Oracle. Vielleicht gibt es an dieser Stelle Probleme. Dürfte aber eigentlich nicht der Fall sein, da ibatis ja noch vor den Preparedstatements sitzt. #limit# ist demnach nur in ibatis sichtbar. Spätestens wenn das PS zusammengebautwird, steht da nur ein ? oder aber bereist der konkrete Wert.

Vielleicht habe ich in einer Klasse irgend etwas für limit und offset zerfetzt. Im Prinzip habe ich eine Klasse, mit gettern und settern, in der limit und offset gesetzt werden. Das ist auch noch so weit korrekt. Vielleicht ist aber eine andere Stelle nicht mehr korrekt (ich hab eine Menge an der App gefummelt).
 
Zurück
Oben