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 ...