[JAVA] [MyBatis] Utilisez le curseur lors du mappage de grandes quantités de données

introduction

Pendant ce temps, au travail, je traitais une grande quantité de données, et j'ai dû revoir le processus qui n'a jamais répondu. Dans l'ensemble, cela a pris environ 4 minutes. Lors de l'examen de ce processus, j'ai modifié Mapper en org.apache.ibatis.cursor.Cursor au lieu de List. En conséquence, nous avons pu accélérer la réponse.

Comme c'est un gros problème, je vais résumer comment utiliser Cursor ajouté dans MyBatis 3.4 ou version ultérieure.

Environnement d'exploitation

Comment utiliser

mapper.xml n'a pas besoin d'être modifié par rapport au moment où vous l'avez obtenu avec List. Puisqu'il traite une grande quantité de données, il serait encore mieux d'ajuster la taille du cache avec fetchSize.

mapper.xml


  <select id="getColumns" fetchSize="50000" resultType="java.lang.String">
    SELECT columns FROM table1
  </select>

Mapper.java importe org.apache.ibatis.cursor.Cursor. Faites correspondre la partie \ à la valeur de retour SQL.

Mapper.java


import org.apache.ibatis.cursor.Cursor;

@Mapper
public interface Mapper {
    public Cursor<String> getColumns();
}

C'est la partie à appeler de Mapper. Similaire à List, sauf que le résultat de l'appel est stocké dans le type Cursor \ .

De plus, la partie qui récupère la valeur par traitement en boucle peut être écrite de la même manière que List. Dans l'exemple, il est écrit en deux types, pour Each et Iterator.

Service.java


@Service
public class Service {
    @Autowired
    private Mapper mapper;

    public void getMapper() {
        try (Cursor<String> columnsCorsor = mapper.getColumns()) {

            //Traitement en boucle 1
            columnsCorsor.forEach(s -> {
                System.out.println(s);
            });

            //Traitement en boucle 2 (notez que la deuxième boucle provoquera une erreur !!)
            Iterator<String> iterator = columnsCorsor.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }

        } catch (Exception e) {
            e.printstacktrace();
        }
    }
}

Il convient de noter que, contrairement à la récupération avec List, **, il sera fermé lorsque toutes les données dans Cursor seront lues **. Par conséquent, si vous récupérez toutes les données une seule fois, puis récupérez à nouveau les données, l'erreur suivante se produit.

java.lang.IllegalStateException: Cannot open more than one iterator on a Cursor

Dans le cas d'une utilisation basique, MyBatis côté va le fermer, donc je pense qu'il n'y a pas de problème.

Cependant, si une erreur se produit au milieu, il n'y a aucune garantie qu'elle sera fermée. Alors, fermons-le ** étroitement ** avec une instruction try ~ resource ou une clause finally au niveau de l'appelant.

finalement

Grâce à Cursor, nous avons pu réduire la réponse de 4 minutes à 2 minutes. (Ceci est le résultat de l'examen des parties autres que Cursor ...) Utilisez le curseur lors du traitement d'une grande quantité de données.

Notes diverses

MyBatis a peu de matériaux de référence, donc je me demande s'il y a peu d'utilisateurs. Quel est le courant dominant des frameworks d'accès aux bases de données ...? MyBatis applique le SQL brut et le mappe bien, donc je l'aime personnellement ... ~~ Je suis parfois ennuyé par les annotations ~~

Les références

MyBatis - MyBatis 3 | Fichier XML du mappeur Cursor | mybatis [5.2. Accès à la base de données (MyBatis3) - Guide de développement de TERASOLUNA Server Framework for Java (5.x) 5.0.1.RELEASE documentation](https://terasolunaorg.github.io/guideline/5.0.1.RELEASE/en/ ArchitectureInDetail / DataAccessMyBatis3.html)

Recommended Posts

[MyBatis] Utilisez le curseur lors du mappage de grandes quantités de données
[MyBatis] Utilisez le curseur lors du mappage de grandes quantités de données
Comment supprimer de grandes quantités de données dans Rails et problèmes
Points lors du mappage d'un objet de valeur dans MyBatis