PostgreSQL Kann mit mybatis einen Parameter für eine postgreSQL-Abfrage nicht übergeben.

pkm

Bekanntes Mitglied
Ich habe eine Funktion:

Java:
   public void goByIdRes(Integer idd) {
      
       SqlSession session = initialise();
      
          session.delete("Resource.deleteById", idd);
          session.commit();
          
          Map<String, Object> map = new HashMap<String, Object>();
          map.put("id", idd);
          map.put("category", "resource");
          //Das bekommt er gebacken.
          session.delete("Link.deleteById", map);     
          session.commit();
          
          ///////////////////////////////////////////////////////////
          
          //In der DB-Tabelle "Resource" will ich alle ids > idd dekrementieren.
          
           Map<String, Object> mapUpdate = new HashMap<String, Object>();
            map.put("id", idd);
          //Das klappt nicht.         
          session.update("Resource.updateById", mapUpdate);     
          session.commit();
          
          session.close();
          
          log.info("Records deleted Successfully.");
   }

Ich benutze eine mybatis - DB-Anbindung, und der Grund, warum ich staune, ist der folgende:

In der Datei Resource.xml ist das SQL für session.delete("Resource.deleteById", map); (siehe Code-Snippet oben) definiert:

XML:
   <delete id = "deleteById">
        DELETE from RESOURCE WHERE ID = #{id};
   </delete>

Dieses Statement klappt.

Nun habe ich ein weiteres Statement (siehe Code):

XML:
   <delete id = "updateById">
         DO $$ DECLARE myvar integer; BEGIN SELECT COUNT(*) FROM RESOURCE INTO myvar; FOR i IN 1..myvar LOOP UPDATE RESOURCE SET ID = i WHERE ID > #{id}; END LOOP; END $$;
   </delete>

Dieses Statement klappt nicht, obwohl ich es in pgAdmin erfolgreich ausführen konnte, wenn ich für #{id} einen festen Wert gesetzt habe, z. B. 1.

Leider werde ich aus dem Fehlerstack nicht schlau, daher dachte ich, ich frage mal hier (falls sich jemand mit myBatis auskennt). Der Fehlerstack ist dieser, und ich habe es auch schon mit #{id,jdbcType=integer} versucht, hat auch nicht geklappt.

org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='id', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting null for parameter #1 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: org.postgresql.util.PSQLException: Der Spaltenindex 1 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 0.
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: DO $$ DECLARE myvar integer; BEGIN SELECT COUNT(*) FROM RESOURCE INTO myvar; FOR i IN 1..myvar LOOP UPDATE RESOURCE SET ID = i WHERE ID > ?; END LOOP; END $$;
### Cause: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='id', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting null for parameter #1 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: org.postgresql.util.PSQLException: Der Spaltenindex 1 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 0.
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:172)
at com.example.vaadin.mybatis.mybatisDelete.goByIdRes(mybatisDelete.java:102)
at com.example.vaadin.views.ResourceView.deleteFromDatasetById(ResourceView.java:199)
at com.example.vaadin.views.ResourceView.lambda$2(ResourceView.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:706)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:399)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:363)
at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1190)
at com.vaadin.ui.renderers.ClickableRenderer.lambda$new$94333610$1(ClickableRenderer.java:138)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:155)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:116)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:442)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:407)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1608)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:448)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='id', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting null for parameter #1 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: org.postgresql.util.PSQLException: Der Spaltenindex 1 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 0.
at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:89)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:85)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:63)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:77)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:115)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:170)
... 47 more
Caused by: org.apache.ibatis.type.TypeException: Error setting null for parameter #1 with JdbcType OTHER . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: org.postgresql.util.PSQLException: Der Spaltenindex 1 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 0.
at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:47)
at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87)
... 54 more
Caused by: org.postgresql.util.PSQLException: Der Spaltenindex 1 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 0.
at org.postgresql.jdbc.PgPreparedStatement.setNull(PgPreparedStatement.java:194)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:67)
at com.sun.proxy.$Proxy17.setNull(Unknown Source)
at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:45)
... 55 more
 
Erstens, hast du deinen Tippfehler, du fuegst den Wert der falschen "Map" hinzu.

Zweitens, bin ich mir nicht sicher ob die Bindung so funktioniert, scheint aber wohl zu gehen.

Drittens, klingt das was du machst komisch. Wenn du willst kannst du die Funktion mal erlaeutern (also was du da in der DB aendern willst) denn ich glaube das geht einfacher.
 
Vielen Dank für den Tipp mit dem Tippfehler!

Also ich habe eine DB-Tabelle Resources mit zwei Spalten: resource (varchar) und id (integer).

Da stehen "Ressourcen" drin, also z. B.

"Trainer Hans Hansen" (resource) 1 (id)
"Trainer Petra Müller" (resource) 2 (id)

Und jetzt drücke ich einen Delete-Button, und ich bin in meinem Funktion:

session.delete("Resource.deleteById", idd);


Wenn ich die Ressource mit der id 1 löschen will, dann fliegt diese aus der Tabelle.

Jetzt ist die ID mit dem geringsten Wert 2. Also "Trainer Petra Müller" (resource) 2 (id)

Ich will also alle Werte mit einer ID größer 1 (die gelöschte ID) um eins dekrementieren:

DO $$ DECLARE myvar integer; BEGIN SELECT COUNT(*) FROM RESOURCE INTO myvar; FOR i IN 1..myvar LOOP UPDATE RESOURCE SET ID = i WHERE ID > #{id}; END LOOP; END $$;

SET ID = i wird also WHERE ID > #{id} gesetzt, und das ist die Dekrementierung, die auch funktioniert, habe es ja als SQL-Statement getestet.

Aber ich hab nach wie vor diesen Fehler:

### Cause: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='id', mode=IN, javaType=class java.lang.Object, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: org.postgresql.util.PSQLException: Der Spaltenindex 1 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 0.

Liegt das vielleich an den $$ ?
 
Warum willst du die IDs denn so ändern, dass es keine Lücken gibt?

(Einfachste Lösung für dein Problem: lass es einfach sein, IDs zu ändern öffnet nur alle Tore zur Hölle, dass hat absolut gar keinen Nutzen. Wenn du eine aufsteigenden Nummer für alle brauchst, nimm besser sowas wie RANK)
 
Wie @mrBrown bereits sagte, wenn es sich hierbei um den primary key (ID) handelt, dann es nicht zu aendern ist die beste Variante, da dies ja der primaere Schluessel ist um genau diesen Eintrag zu finden. Wenn du jemals die Zeile damit referenzierst, und in der Zwischenzeit eine Zeile geloescht wird kann das sehr schnell zu Problemen fuehren. Von Foreign Keys mal ganz abgesehen.

Liegt das vielleich an den $$ ?
Wie ich bereits sagt, ich *glaube* du kannst die Parameter nicht innerhalb von einem solchen Statement/Function binden. Da muesstest du im Zweifelsfall mal kurz in der Dokumentation von MYBATIS und den PostgreSQL JDBC Treiber nachschauen ob es moeglich ist.
 
Hm, ok, dann lass ich es am besten mit der Änderung der IDs, also öffne ich nicht alle Tore zur Hölle ^ ^

Besten Dank für die Tipps!
 

Neue Themen


Zurück
Oben