7 Stimmen

Verschachteltes foreach in MyBatis 3 für einen HashMap-Parameter

Ich versuche, eine Lösung für das folgende Problem mit MyBatis 3.0.6 herauszufinden:

Ich muss eine dynamische Select-Anweisung erstellen, die auf einer Reihe von Parametern basiert, von denen einer vom Typ HashMap<String, List<String>> . Die Herausforderung besteht darin, herauszufinden, wie man MyBatis dazu bringt, über alle Schlüssel in einem äußeren Verzeichnis zu iterieren. foreach Schleife sowie über die Elemente der Werteliste in der inneren Schleife zu iterieren.

Zur Veranschaulichung: Angenommen, mein Hash-Map-Parameter heißt Filter enthält Staaten (Listen von Staatencodes, jede Liste ist der Wert) pro Land (Ländercode als Schlüssel) wie folgt:

'US' -> {'CO','NY','MI','AZ'};
'CA' -> {'ON','BC','QC'}

Mein dynamisches SQL muss wie folgt aussehen (in stark vereinfachter Form):

SELECT *
FROM  Table1
WHERE ... some static criteria goes here...
      AND RowId IN (SELECT RowId FROM Table2 WHERE Country = 'US' AND State IN ('CO','NY','MI','AZ')
      AND RowId IN (SELECT RowId FROM Table2 WHERE Country = 'CA' AND State IN ('ON','BC,'QC')

Ich könnte mir vorstellen, dass mein Mapper-XML etwa so aussehen sollte:

<select id="getData" resultType="QueryResult">
SELECT *
FROM  Table1
WHERE ... some static criteria goes here...
     <if test="filter != null">
         <foreach item="country" index="i" collection="filter" separator="AND">
             RowId IN (SELECT RowId 
                       FROM Table2 
                       WHERE Country = #{country} AND State IN
             <foreach item="state" index="j" collection="country.states" separator="," open="(" close=")">
                 #{state}
             </foreach>
         </foreach>
     </if>
</select>

Die Frage ist also, wie lautet die richtige Syntax, um die Länder.Staaten für die Iteration in der verschachtelten foreach Schleife?


UPDATE

Nach einigem Herumprobieren konnte ich MyBatis nicht dazu bringen, mit dem HashMap-basierten Ansatz mitzuspielen, also fügte ich schließlich eine neue Klasse hinzu, die mehrere Werte auf ihren übergeordneten Wert abbildet, und übergab dann eine Liste solcher Objekte an MyBatis. Anhand des obigen Länder/Staaten-Beispiels sieht die Klasse wie folgt aus:

public class Filter {
   private String country;
   private ArrayList<String> states;

   // ... public get accessors here ...
}

Die DAO-Methode:

public void QueryResult[] getResults( @Param("criteria") List<Filter> criteria) ...

Und die MyBatis-Zuordnung:

<select id="getData" resultType="QueryResult">
SELECT *
FROM  Table1
WHERE ... some static criteria goes here...
     <if test="criteria!= null">
         <foreach item="filter" index="i" collection="criteria" separator="AND" open="AND">
             RowId IN (SELECT RowId 
                       FROM Table2 
                       WHERE Country = #{filter.country} AND State IN
             <foreach item="state" index="j" collection="filter.states" separator="," open="(" close=")">
                 #{state}
             </foreach>
         </foreach>
     </if>
</select>

Funktioniert wie ein Zauber.

3voto

user1738084 Punkte 31

Sie können den Länderwert verwenden, um ihn in der Filterkarte nachzuschlagen, so dass er wieder so funktioniert, wie Sie ihn ursprünglich hatten. In der zweiten Schleife wird Ihre Sammlung wie folgt definiert filter.get(country) und das sollte gut sein. Das gilt natürlich nur, wenn ich Ihre Frage richtig interpretiere.

1voto

tariq zafar Punkte 637

Ich hatte etwas, das als Karte eingefügt werden sollte, wobei jeder Kartenschlüssel einer Liste zugeordnet war. Ich schrieb die Abfrage auf diese Weise.

INSERT INTO TB_TEST (group_id, student_id) VALUES
<foreach collection="idMap.entrySet()" item="element" index="index" separator=",">
         <foreach collection="element.value" item="item" separator="," > 
            ( #{element.key}  #{item} )     
         </foreach> 
    </foreach>

1voto

Jin Kwon Punkte 18020

Ab sofort kann ich das tun.

<foreach collection="myMap" index="key" item="value">
  <foreach collection="value" item="element">
    ... = #{key} ...
    ... = #{element})
  </foreach>
</foreach>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X