java – Paging-Problem mit mehreren Tabellen in der Mybatis-Datenbank
黄舟
黄舟 2017-06-10 09:49:39
0
6
1532

Zum Beispiel:
Es gibt zwei Entitätsklassen Benutzer und 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...
}

Datenbank:

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)
);

Mybatis-Zuordnungskonfiguration:


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

Die Beziehung zwischen Benutzern und Adressen ist: Ein Benutzer hat mehrere Adressen, eine Adresse kann nur einem Benutzer gehören, eins zu viele
Angenommen, die aktuelle Anforderung besteht darin, Benutzer auf Seiten abzufragen, sie in einer Tabelle anzuzeigen und alle anzuzeigen Die Adressen jedes Benutzers kommen heraus
Dann kommt das Problem
Es gibt kein Problem mit den Paging-Daten, die gemäß der obigen Abfrage zurückgegeben werden, aber die Gesamtzahl der Paging-Datensätze ist falsch.
Die gefundenen Daten (Datenbankdaten, nicht Seitenanzeige) lauten beispielsweise wie folgt:

u_id Benutzername a_id Detail
1 Benutzer1 1 Bezirk Haidian, Peking
1 Benutzer1 2 Bezirk Chaoyang, Peking
2 Benutzer2 3 Stadt Tianjin

Da meine Anforderung darin besteht, Benutzer auf Seiten anzuzeigen, handelt es sich bei einem Benutzer um ein auf der Seite angezeigtes Datenelement, das so aussieht. Theoretisch handelt es sich um zwei Datenelemente,

Benutzer-ID Benutzername Adresse
1 Benutzer1 1. Bezirk Haidian, Peking 2. Bezirk Chaoyang, Peking
2 Benutzer2 1. Tianjin-Stadt
1 Seite insgesamt, 2 Datenteile insgesamt, 10 Teile werden auf jeder Seite angezeigt

Laut der find_count-Konfiguration von mybatis wurde jedoch festgestellt, dass es drei Elemente gibt.
Sollten bei der Abfrage von count(*) alle mit dem Left Join verknüpften Tabellen entfernt werden? Führt dies dazu, dass die zurückgegebenen Daten ungenau sind?


Zusätzliche Erklärung: Ich habe das Gefühl, dass jeder falsch verstanden hat, was ich meinte. Tatsächlich liegt mein Problem hauptsächlich bei SQL, nicht bei Mybatis, da es nach der Zuordnung der von mir abgefragten Daten überhaupt kein Problem gab, sondern nur das Paging Es liegt ein Problem mit der Gesamtzahl der Datensätze vor, was zu einer falschen Paginierung führt

黄舟
黄舟

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

Antworte allen(6)
漂亮男人

刚才写了个例子测了一下

`

两个实体类
public class User {


private int id;
private String username; // 用户名
private List<Address> addresses;

public class Address {

private int id;
private String detail; // 详细地址
private int user_id; // 所属用户

映射文件
<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" >

<!-- select tu.,ta., -->
<!-- ta.id as 'a_id', -->
<!-- tu.id as 'u_id' -->
<!-- from t_user tu , -->
<!-- t_address ta where 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>

测试结果

封装成的 List<User>的size是没问题的

左手右手慢动作

关键词group by 自己查一下具体操作

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

你希望想要两条 但是你的sql查出三条,所以显示错误,
应该拆分逻辑:
应该先查出你想要的用户

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

然后在

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

??是自己实现个 用userId查List<Address>的方法

学霸

这种情况不能这么分页,你需要对主表数据进行分页。

本来查询出100条数据,由于一对多会折叠去重很多数据,导致实际结果少于100条。

这种情况下可以采取嵌套查询方式解决,就是需要N+1次执行,可以懒加载。

或者看这里:https://my.oschina.net/flags/...

有关 MyBatis 内容可以访问: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> 

改:

<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> 
曾经蜡笔没有小新

用子查询就不会有问题了

select count(*) from (
   // query 在这里即使关联100张表, 也不可能存在问题
)

楼主可以看一下Mybatis-PageHelper count sql 转换实现

建议楼主直接使用 Mybatis-PageHelper 实现分页

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage