[JAVA] Utilisez MyBatis pour obtenir une carte avec une clé comme identifiant et une valeur comme entité

Comme le dit le titre.

Les scénarios d'utilisation possibles sont les suivants, par exemple.

Considérez le tableau suivant comme exemple.

Employee Department SubDepartment
id PK id PK employee_id FK
name name department_id FK
mail_address
department_id FK
department_name

Entity(Omettre le package et importer)


//Entité des employés
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeEntity {

    private int id;

    private String name;

    private String mailAddress;

    private int departmentId;

    private String departmentName;

    //Organisation simultanée
    private List<DepartmentEntity> subDepartments;
}

//Organisation d'affiliation Entité
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DepartmentEntity {

    private int id;

    private String name;
}

Lorsque vous souhaitez obtenir la structure suivante, il semble qu'il ne soit pas possible de l'obtenir d'un seul coup uniquement avec la fonction MyBatis.

Structure requise


{
  "1" : {
    "id" : 1,
    "name" : "John",
    "mailAddress" : "[email protected]",
    "departmentId" : 1,
    "departmentName" : "Planning",
    "subDepartments" : [ ]
  },
  "2" : {
    "id" : 2,
    "name" : "Ken",
    "mailAddress" : "[email protected]",
    "departmentId" : 1,
    "departmentName" : "Planning",
    "subDepartments" : [ {
      "id" : 2,
      "name" : "Legal"
    }, {
      "id" : 3,
      "name" : "Investor Relations"
    } ]
  }
}

Par conséquent, médiez la classe MappingHelper afin que la structure ci-dessus puisse être obtenue. Les informations sont obtenues de la base de données sous forme de liste de MappingHelper et converties en Map à l'aide de MappingHelper # toMap. Gardez les types de données clé et valeur génériques afin de pouvoir les spécifier lors de la définition de l'interface pour la requête que vous émettez.

MappingHelper.java


package com.example.domain.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MappingHelper<K, V> {

    private K key;

    private V value;

    public static <K, V> Map<K, V> toMap(List<MappingHelper<K, V>> list) {
        if (list == null) {
            return Collections.emptyMap();
        }
        return list.parallelStream().collect(Collectors.toMap(MappingHelper::getKey, MappingHelper::getValue));
    }
}

Utilisez cette classe MappingHelper pour créer le mappeur MyBatis suivant.

EmployeeRepository.java


package com.example.domain.repository;

import com.example.domain.model.EmployeeEntity;
import com.example.domain.model.MappingHelper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@Mapper
public interface EmployeeRepository  {

    List<MappingHelper<Integer, EmployeeEntity>> findAllByIds(@Param("ids") List<Integer> ids);
}

EmployeeRepository.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.domain.repository.EmployeeRepository">

    <select id="findAllByIds" resultMap="employeeMapHelper">
        SELECT
          e.id employeeId,
          e.name employeeName,
          e.mail_address mailAddress,
          d.id departmentId,
          d.name departmentName,
          sd.id subDepartmentId,
          sd.name subDepartmentName
        FROM
          employee e
        LEFT JOIN
          department d
        ON
          e.department_id = d.id
        LEFT JOIN (
          SELECT
            d2.id,
            d2.name,
            sd2.employee_id
          FROM
            sub_department sd2
          INNER JOIN
            department d2
          ON
            d2.id = sd2.department_id
          WHERE
            sd2.employee_id IN
            <foreach collection="ids" item="id" open="(" close=")" separator=",">
              #{id}
            </foreach>
        ) sd
        ON
          e.id = sd.employee_id
        WHERE
          e.id IN
          <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
          </foreach>
    </select>

    <resultMap id="employeeMapHelper" type="MappingHelper">
        <id property="key" column="employeeId" javaType="String"/>
        <association property="value" resultMap="employeeMap"/>
    </resultMap>

    <resultMap id="employeeMap" type="EmployeeEntity">
        <id property="id" column="employeeId"/>
        <result property="name" column="employeeName"/>
        <result property="mailAddress" column="mailAddress"/>
        <result property="departmentId" column="departmentId"/>
        <result property="departmentName" column="departmentName"/>
        <collection property="subDepartments" ofType="DepartmentEntity">
            <id property="id" column="subDepartmentId"/>
            <result property="name" column="subDepartmentName"/>
        </collection>
    </resultMap>
</mapper>

Vous pouvez obtenir la structure cible en exécutant le traitement suivant en utilisant ce qui précède.

SandboxRestController.java


package com.example.web;

import com.example.domain.model.EmployeeEntity;
import com.example.domain.model.MappingHelper;
import com.example.domain.repository.EmployeeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequiredArgsConstructor
public class SandboxRestController {

    private final EmployeeRepository employeeRepository;

    @RequestMapping("/mybatisToMap")
    public ResponseEntity<Map> mybatisToMap() {
        List<MappingHelper<Integer, EmployeeEntity>> mapperList = employeeRepository.findAllByIds(Arrays.asList(1, 2));
        Map<Integer, EmployeeEntity> employeeMap = MappingHelper.toMap(mapperList);
        return ResponseEntity.ok().body(employeeMap);
    }
}

Avec ce qui précède, vous pouvez obtenir une carte avec la clé comme identifiant et la valeur comme entité en utilisant MyBatis. Cela peut être utile lors de l'implémentation avec Java lorsque la jointure de table n'est pas possible.

Exemple de code: https://github.com/tnemotox/sandbox Référence: https://stackoverflow.com/questions/36400538/mybatis-resultmap-is-hashmapstring-object


Post-scriptum: 18/6/14

Avec Java, même si vous ne vous souciez pas de faire de votre mieux avec MyBatis, vous pouvez obtenir une liste et faire de votre mieux avec Stream ... Il y a des moments où vous voulez une liste, vous pouvez donc la créer en une seule fois à partir des résultats de cette requête.

De la liste à la carte avec flux


Map<Integer, EmployeeEntity> employeeMap = employees.stream().collect(toMap(EmployeeEntity::getEmployeeId, e -> e, (e1, e2) -> e1);

Eh bien, cela pourrait être utile ...

Recommended Posts

Utilisez MyBatis pour obtenir une carte avec une clé comme identifiant et une valeur comme entité
Comment utiliser MyBatis2 (iBatis) avec Spring Boot 1.4 (Spring 4)
Essayez d'obtenir la clé API de redmine avec ruby
Comment utiliser Map
Comment utiliser Map
Comment ajouter un autre projet en tant que bibliothèque Maven avec CircleCI et l'utiliser pour la construction
Avec podman dans docker, tout le monde veut s'entendre et utiliser docker avec un ordinateur partagé
Comment exécuter JUnit par lots et obtenir une couverture
[Spring Boot] Je veux ajouter mon propre fichier de propriétés et obtenir la valeur avec env.getProperty ().
Comment utiliser le certificat et la clé privée créés par l'authentification BASIC de Docker avec AWS ALB
[Java] Comment utiliser Map
Utilisez un filtre et une carte rapides
Comment utiliser Java Map
Comment obtenir l'identifiant de la clé PRIMAY incrémentée automatiquement dans MyBatis
Comment obtenir la valeur de boolean avec jQuery sous forme simple de rails