Mybatis foreach itération sur liste d'entiers à l'intérieur d'un objet complexe paramètre

Je suis à l'aide de MyBatis 3.2.8 dans une pièce de théâtre Cadre 2.3.6 projet Java. J'ai eu du mal pendant plusieurs jours avec une itération sur une liste d'entiers qui est transmis à un MyBatis mappeur au sein d'un complexe de paramètre de l'objet. Voici ma configuration:

J'ai une classe appelée EventFilter dans EventFilter.java:

public class EventFilter {
private String beginDate;
private String endDate;
private List<Integer> closestCountry;
private List<Integer> territorialWaterStatus;
private List<Integer> vesselCountry;
private String closestCountryInClause;
private String territorialWaterStatusInClause;
private String vesselCountryInClause;
public EventFilter() { }
public EventFilter(JsonNode jsonNode){
this.beginDate = jsonNode.get("beginDate").asText();
this.endDate = jsonNode.get("endDate").asText();
this.closestCountry = JsonHelper.arrayNodeToIntegerList((ArrayNode) jsonNode.get("closestCountry"));
this.territorialWaterStatus = JsonHelper.arrayNodeToIntegerList((ArrayNode) jsonNode.get("territorialWaterStatus"));
this.vesselCountry = JsonHelper.arrayNodeToIntegerList((ArrayNode) jsonNode.get("vesselCountry"));
}
public String getBeginDate() {
return beginDate;
}
public void setBeginDate(String beginDate) {
this.beginDate = beginDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public List<Integer> getTerritorialWaterStatus() {
if(this.territorialWaterStatus.size() > 0) {
return territorialWaterStatus;
} else {
return null;
}
}
public void setTerritorialWaterStatus(List<Integer> territorialWaterStatus) {
this.territorialWaterStatus = territorialWaterStatus;
}
public List<Integer> getClosestCountry() {
if(this.closestCountry.size() > 0) {
return closestCountry;
} else {
return null;
}
}
public void setClosestCountry(List<Integer> closestCountry) {
this.closestCountry = closestCountry;
}
public List<Integer> getVesselCountry() {
if(this.vesselCountry.size() > 0) {
return vesselCountry;
} else {
return null;
}
}
public void setVesselCountry(List<Integer> vesselCountry) {
this.vesselCountry = vesselCountry;
}

}

Cela est référencée comme un alias de type dans mon mybatis fichier de config:

<configuration>
<typeAliases>
<typeAlias type="models.Event" alias="Event"/>
<typeAlias type="models.EventFilter" alias="EventFilter"/>
<typeAlias type="models.Country" alias="Country"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/mpmap"/>
<property name="username" value="postgres"/>
<property name="password" value="dbpw"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="EventMapper.xml"/>
</mappers>
</configuration>

J'ai un mappeur qui prend un EventFilter objet comme paramètre. Elle doit alors vérifier si le beginDate, date_fin, closestCountry, vesselCountry, et territorialWaterStatus sont fixés. Si ils sont il les utilise pour la clause where:

<select id="getEventsWithFilter" resultType="Event" resultMap="EventResult">
SELECT ev.id, to_char(ev.occurred_on, 'YYYY-MM-DD') AS occurred_on_date,
to_char(ev.occurred_on, 'HH24:MI:SS') AS occurred_on_time,
ST_X(ev.location) AS longitude, ST_Y(ev.location) AS latitude,
COALESCE(co01.name, 'Unspecified') AS closest_country,
COALESCE(co02.name, 'Unspecified') AS territorial_water_status,
COALESCE(co03.name, 'Unspecified') AS vessel_flag_country
FROM event AS ev
LEFT JOIN country AS co01
ON co01.cow_id = ev.location_closest_country_id
LEFT JOIN country AS co02
ON co02.cow_id = ev.location_water_status_country_id
LEFT JOIN country AS co03
ON co03.cow_id = ev.vessel_flag_country_id
<where>
<if test="#{eventFilter.beginDate} != null and #{eventFilter.endDate} != null">
ev.occurred_on &gt;= #{eventFilter.beginDate}::timestamp AND ev.occurred_on &lt;= #{eventFilter.endDate}::timestamp
</if>
<if test="#{eventFilter.closestCountry} != null">
AND ev.location_closest_country_id IN
<foreach item="id" index="index" collection="#{eventFilter.closestCountry}" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<if test="#{eventFilter.territorialWaterStatus} != null">
AND ev.location_water_status_country_id IN
<foreach item="id" index="index" collection="#{eventFilter.territorialWaterStatus}" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<if test="#{eventFilter.vesselCountry} != null">
AND ev.vessel_flag_country_id IN
<foreach item="id" index="index" collection="#{eventFilter.vesselCountry}" open="(" separator="," close=")">
#{id}
</foreach>
</if>
</where>
ORDER BY ev.occurred_on ASC;
</select>

J'ai le mappeur lié à une interface comme suit:

    public List<Event> getEventsWithFilter(@Param("eventFilter") EventFilter eventFilter);

Et je l'appelle avec un MybatisMapper de la classe helper qui génère ma session comme suit:

public static List<Event> getEvents(EventFilter eventFilter) {
MybatisMapper mapper = new MybatisMapper();
SqlSession session = mapper.getSession();
EventMapper eventMapper = session.getMapper(EventMapper.class);
List<Event> events;
List<Integer> li = eventFilter.getClosestCountry();
try {
events = eventMapper.getEventsWithFilter(eventFilter);
} finally {
session.close();
}
return events;
}

Le Problème(s):

La beginDate et la date de fin des travaux tout à fait acceptable par eux-mêmes. Mais je vais avoir des problèmes suivants avec les listes d'entiers:

  1. L'instruction if vérifie si la liste est null semble
    ignoré, ou de l'évaluation de vrai quand il doit être fausse.
  2. Les listes d'entiers apparaissent être passé comme une valeur null dans les clauses.
  3. Si j'commentaire de la liste d'entiers DANS les clauses, et juste pour beginDate et
    date de fin, il fonctionne tout à fait acceptable. Cependant, si je quitte la entier
    liste des clauses, la requête n'est pas en panne, mais elle renvoie un vide
    ensemble, comme pour dire "OÙ la colonne ()".

Voici la journalisation de la console imprimé par le Jeu et Mybatis lorsque le mappeur/requêtes sont exécutées, avec la EventFilter l'impression de son contenu. Ils sont un peu long alors je les ai mis dans pastebin:

C'est devenu un peu plus longtemps que je le voulais, mais merci d'avance pour toute aide ou suggestion.

Aussi, ici, est le journal de débogage quand je commenter les trois derniers si les déclarations et les itérations dans le mappeur: pastebin.com/6feWzd0D
Je suis incapable de voir vos journaux à cause de mon restrictions de pare-feu, mais se pourrait-il que celui qui est le remplissage de EventFilter (deviner votre framework MVC) n'est pas l'alimenter correctement car vous utilisez une Liste<Integer> contrairement à un tableau de type de données primitif?
Hmm. Ok, donc à utiliser un tableau d'entiers au lieu d'une liste d'entiers? Selon toutes les indications de la mybatis foreach semble être la liste et la carte sympathique, mais je vais vous donner que d'essayer.
Ce que je suggère est de s'assurer que les données sont remplies avant d'appeler myBatis mapper, c'est à dire dans getEvents, simplement examiner si la liste d'Entiers est peuplée d'abord avant de me douter de myBatis. Encore une fois, vous pouvez l'ai fait et il s'affiche dans les journaux, mais je ne peux pas le voir. Si c'est là, essayez d'utiliser un tableau de primitives de type de données int.
Aha oui je l'ai fait et la liste est remplie avant la eventfilter objet est passé à la mappeur. Je vais essayer de le changer pour un type primitif, mais je préfère le garder comme il est, si possible,

OriginalL'auteur Alex Klibisz | 2014-12-24