Maison > Questions et réponses > le corps du texte
Par exemple :
Il existe deux classes d'entités Utilisateur et Adresse
public class User {
private int id;
private String username; // 用户名
private List<Address> addresses;
// getter setter...
}
public class Address {
private int id;
private String detail; // 详细地址
private User user; //所属用户
// getter setter...
}
Base de données :
create table t_user(
id int(10) primary key auto_increment,
username varchar(50)
);
create table t_address(
id int(10) primary key auto_increment,
detail varchar(255),
user_id int(10),
CONSTRAINT FOREIGN KEY (user_id) REFERENCES t_user(id)
);
Configuration de la cartographie mybatis :
<?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="org.mkh.shop.model.User">
<resultMap type="User" id="userMap" autoMapping="true">
<id property="id" column="u_id"/>
<collection property="address" ofType="Address">
<id property="id" column="a_id"/>
<result property="detail" column="detail"/>
</collection>
</resultMap>
<select id="find" resultType="User" parameterType="map">
select *,
ta.id as 'a_id',
tu.id as 'u_id'
from t_user tu
left join t_address ta on ta.user_id=tu.id
<where>
<if test="name != null">
(username like #{name})
</if>
</where>
<if test="sort != null">
order by ${sort}
<choose>
<when test="order != null">${order}</when>
<otherwise>asc</otherwise>
</choose>
</if>
limit #{pageOffset},#{pageSize}
</select>
<select id="find_count" resultType="int" parameterType="map">
select count(*)
from t_user tu
left join t_address ta on ta.user_id=tu.id
<where>
<if test="name != null">
(username like #{name})
</if>
</where>
</select>
</mapper>
La relation entre les utilisateurs et les adresses est la suivante : un utilisateur a plusieurs adresses, une adresse ne peut appartenir qu'à un seul utilisateur, une à plusieurs
Supposons que la demande actuelle soit d'interroger les utilisateurs dans des pages, de les afficher dans un tableau et de tous les afficher. adresses de chaque utilisateur Sortez
Ensuite, le problème survient
Il n'y a aucun problème avec les données de pagination renvoyées selon la requête ci-dessus, mais le nombre total d'enregistrements de pagination est erroné.
Par exemple, les données trouvées (données de la base de données, pas affichage de la page) sont les suivantes :
u_id | nom d'utilisateur | a_id | détail |
---|---|---|---|
1 | utilisateur1 | 1 | District de Haidian, Pékin |
1 | utilisateur1 | 2 | District de Chaoyang, Pékin |
2 | utilisateur2 | 3 | Ville de Tianjin |
Parce que mon exigence est d'afficher les utilisateurs dans des pages, un utilisateur est donc une donnée affichée sur la page, qui ressemble à ceci. En théorie, il s'agit de deux données,
.ID utilisateur | Nom d'utilisateur | Adresse |
---|---|---|
1 | utilisateur1 | 1. District de Haidian, Pékin 2. District de Chaoyang, Pékin |
2 | utilisateur2 | 1. Ville de Tianjin |
1 page au total, 2 éléments de données au total, 10 éléments affichés sur chaque page |
Cependant, d'après la configuration find_count de mybatis, on constate qu'il y a 3 éléments. Comment résoudre ce problème ?
Lors de l'interrogation de count(*), toutes les tables associées à la jointure gauche doivent-elles être supprimées ? Cela rendra-t-il les données renvoyées inexactes ?
Explication supplémentaire : j'ai l'impression que tout le monde a mal compris ce que je voulais dire. En fait, mon problème concerne principalement SQL, pas mybatis, car une fois les données que j'ai interrogées ont été mappées, il n'y a eu aucun problème, c'était juste une pagination. il y a un problème avec le nombre total d'enregistrements, entraînant une pagination incorrecte
漂亮男人2017-06-10 09:51:39
Je viens d'écrire un exemple et de le tester
`
Deux classes d'entités
classe publique Utilisateur {
private int id;
private String username; // 用户名
private List<Address> addresses;
Adresse de classe publique {
private int id;
private String detail; // 详细地址
private int user_id; // 所属用户
Fichier de cartographie
<resultMap type="com.atguigu.mybatis.entity.User" id="userMap" autoMapping="true">
<result property="id" column="u_id"/>
<collection property="addresses" ofType="com.atguigu.mybatis.entity.Address" autoMapping="true">
<result property="id" column="a_id"/>
<result property="user_id" column="u_id"/>
</collection>
</resultMap>
<select id="select_all_user_address" resultMap="userMap" >
<!-- sélectionnez tu.,ta., -->
<!-- ta.id comme 'a_id', -->
<!-- tu.id comme 'u_id' -->
<!-- de t_user tu , -->
<!-- t_address ta où ta.user_id=tu.id -->
select tu.*,ta.*,
ta.id as 'a_id',
tu.id as 'u_id'
from t_user tu
left join t_address ta on ta.user_id=tu.id
</select>
Résultats des tests
La taille de la liste encapsulée<Utilisateur> ne pose aucun problème
ringa_lee2017-06-10 09:51:39
Regroupez les mots clés par et vérifiez vous-même l'opération spécifique
欧阳克2017-06-10 09:51:39
SELECT
*, ta.id AS 'a_id', tu.id AS 'u_id'
FROM
t_user tu
LEFT JOIN
t_address ta ON ta.user_id = tu.id;
Vous espérez vouloir deux éléments, mais votre SQL trouve trois éléments, donc une erreur s'affiche
Vous devez diviser la logique :
Vous devez d'abord trouver l'utilisateur que vous souhaitez
<select id="find" resultType="User" parameterType="map">
select *
from t_user tu
<where>
<if test="name != null">
(username like #{name})
</if>
</where>
<if test="sort != null">
order by ${sort}
<choose>
<when test="order != null">${order}</when>
<otherwise>asc</otherwise>
</choose>
</if>
limit #{pageOffset},#{pageSize}
</select>
Puis dans
<resultMap type="User" id="userMap" autoMapping="true">
<id property="id" column="u_id"/>
<collection " property="addresses" javaType= "ArrayList" column="u_id"
ofType="Address" select= "??" />
</resultMap>
??C'est une méthode pour vérifier List<Address> en utilisant l'ID utilisateur par vous-même
欧阳克2017-06-10 09:51:39
Dans ce cas, la pagination ne peut pas être effectuée de cette manière. Vous devez paginer les données de la table principale.
À l'origine, 100 éléments de données ont été interrogés, mais comme un vers plusieurs pliera et dédupliquera un grand nombre de données, les résultats réels étaient inférieurs à 100 éléments.
Dans ce cas, une requête imbriquée peut être utilisée pour résoudre le problème, qui nécessite N+1 exécutions et peut être chargée paresseusement.
Ou regardez ici : https://my.oschina.net/flags/...
Pour le contenu MyBatis, veuillez visiter : http://mybatis.tk
扔个三星炸死你2017-06-10 09:51:39
<select id="find_count" resultType="int" parameterType="map">
select count(*)
from t_user tu
left join t_address ta on ta.user_id=tu.id
<where>
<if test="name != null">
(username like #{name})
</if>
</where>
</select>
Modifier :
<select id="find_count" resultType="int" parameterType="map">
select count(*)
from t_user tu
<where>
<if test="name != null">
(username like #{name})
</if>
</where>
group by username
</select>
曾经蜡笔没有小新2017-06-10 09:51:39
Il n'y aura aucun problème si vous utilisez une sous-requête
select count(*) from (
// query 在这里即使关联100张表, 也不可能存在问题
)
L'auteur peut jeter un œil à Mybatis-PageHelper
implémentation de la conversion SQL
Il est recommandé à l'auteur d'utiliser directement Mybatis-PageHelper pour implémenter la pagination