java - Problème de pagination lié à plusieurs tables de la base de données Mybatis
黄舟
黄舟 2017-06-10 09:49:39
0
6
1535

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

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

répondre à tous(6)
漂亮男人

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

左手右手慢动作

Regroupez les mots clés par et vérifiez vous-même l'opération spécifique

学霸
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

学霸

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

扔个三星炸死你
<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> 
曾经蜡笔没有小新

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

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal