V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
samples
V2EX  ›  Java

Java 一对多的数据怎样获取 可以提高性能

  •  2
     
  •   samples · 2018-08-31 16:16:29 +08:00 · 2944 次点击
    这是一个创建于 2274 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设有两个对象 A,B 且是 1 对多的关系

    class A {

    int id;
    
    List<B> bs;
    

    }

    class B {

    int a_id;
    
    String name;
    

    }

    现在需要获取 A 的列表。

    1. 先获取 A 的列表,然后遍历通过 a_id 获取对应的 B 的列表,再 set 进 A,这样多次 io 较慢

    2. 用 sql join 将全部数据从数据库中取出,在内存中运算筛选封装。

    问下大佬们有没有更好的做法?先谢为敬

    8 条回复    2018-09-03 17:57:36 +08:00
    Eugene1024
        1
    Eugene1024  
       2018-08-31 17:25:24 +08:00
    直接
    class C

    {
    int a_id;
    int b_id;
    String name;
    }
    前端显示 C,a_id 相同的合并,我的理解
    vjnjc
        2
    vjnjc  
       2018-08-31 19:46:16 +08:00 via Android
    看你业务,假如不同 aid 对应的 blist 有交集的话,做一个 b 对象的缓存。就是已经读取过的 b 都还存在内存 cache 里,Hashmap ( id,b ) bcache=new Hashmap...
    mmdsun
        3
    mmdsun  
       2018-08-31 20:22:57 +08:00 via Android
    mybatis collection 处理一对多配置好就直接查出来了 sql join。大表不方便连表可以用第一种。
    talen666
        4
    talen666  
       2018-08-31 22:15:53 +08:00
    同意楼上 mybatis collection。
    TommyLemon
        5
    TommyLemon  
       2018-08-31 23:52:08 +08:00
    JOIN 直接就解决了,只取需要的而不是全部数据,为啥还要在内存中(我的理解是应用层,而不是数据库引擎)筛选?
    ```sql
    SELECT A.*, B.* FROM A INNER JOIN B ON A.id = B.a_id WHERE {A 和 B 里面字段的条件}
    ```

    封装是肯定要在应用层搞定的,遍历 ResultSet 再封装 A,B 即可,A 很可能会有重复,所以最好用
    ```java
    Map<a_id, A> aMap = new LinkedHashMap<>();
    ```
    这样的结构,每次
    ```java
    A a = aMap.get(a_id);
    if (a == null) {
    a = new A();
    aMap.put(a_id, A);
    }
    a.setId(a_id);
    ...

    List<B> bs = a.getBs();
    if (bs == null) {
    bs = new ArrayList<>();
    a.setBs(bs);
    }

    B b = new B();
    b.setA_id(a_id);
    ...
    bs.add(b);
    ```

    如果你懒得封装,其实可以用 APIJSON 的自动化 API 帮你搞定:
    请求
    ```javascript
    {
    "Moment": {},
    "Comment[]": { //把数组里面每项的 Comment 对象提取出来
    "Comment": {
    "momentId@": "Moment/id" // 引用赋值:Comment.momentId = Moment.id
    }
    }
    }
    ```
    返回:
    ```javascript
    {
    "Moment": {
    "id": 12,
    "userId": 70793,
    "date": "2017-02-08 16:06:11.0",
    "content": "1111534034",
    "praiseUserIdList": [
    70793,
    93793
    ],
    "pictureList": [
    "http://static.oschina.net/uploads/img/201604/22172508_eGDi.jpg"
    ]
    },
    "Comment[]": [
    {
    "id": 162,
    "toId": 0,
    "userId": 93793,
    "momentId": 12,
    "date": "2017-03-06 13:03:45.0",
    "content": "This is a Content...-162"
    },
    {
    "id": 164,
    "toId": 0,
    "userId": 93793,
    "momentId": 12,
    "date": "2017-03-06 13:03:45.0",
    "content": "This is a Content...-164"
    },
    {
    "id": 172,
    "toId": 162,
    "userId": 82001,
    "momentId": 12,
    "date": "2017-03-25 20:22:58.0",
    "content": "OK"
    }
    ],
    "code": 200,
    "msg": "success"
    }
    ```

    APIJSON 自动将前端传的 JSON 参数转为 SQL 语句执行并返回结果,
    期间自动校验权限、结构、内容,自动防 SQL 注入。

    通过自动化 API,前端可以定制任何数据、任何结构!
    大部分 HTTP 请求后端再也不用写接口了,更不用写文档了!
    前端再也不用和后端沟通接口或文档问题了!再也不会被文档各种错误坑了!
    后端再也不用为了兼容旧接口写新版接口和文档了!再也不会被前端随时随地没完没了地烦了!

    在线解析
    自动生成文档,清晰可读永远最新
    自动生成请求代码,支持 Android 和 iOS
    自动生成 JavaBean 文件,一键下载
    自动管理与测试接口用例,一键共享
    自动校验与格式化 JSON,支持高亮和收展

    对于前端
    不用再向后端催接口、求文档
    数据和结构完全定制,要啥有啥
    看请求知结果,所求即所得
    可一次获取任何数据、任何结构
    能去除重复数据,节省流量提高速度

    对于后端
    提供通用接口,大部分 API 不用再写
    自动生成文档,不用再编写和维护
    自动校验权限、自动管理版本、自动防 SQL 注入
    开放 API 无需划分版本,始终保持兼容
    支持增删改查、模糊搜索、正则匹配、远程函数等

    后端接口和文档自动化,前端(客户端) 定制返回 JSON 的数据和结构!
    创作不易,GitHub 右上角点 Star 支持下吧,谢谢^_^
    github.com/TommyLemon/APIJSON
    TommyLemon
        6
    TommyLemon  
       2018-08-31 23:56:53 +08:00
    @TommyLemon 纯手打,有个错误,
    Map<a_id, A> aMap = new LinkedHashMap<>();
    要改成
    Map<Integer, A> aMap = new LinkedHashMap<>();
    TommyLemon
        7
    TommyLemon  
       2018-08-31 23:58:38 +08:00
    @TommyLemon INNER JOIN 可实现多表条件组合,如果只是根据 A 取 B,应该改用 LEFT JOIN
    samples
        8
    samples  
    OP
       2018-09-03 17:57:36 +08:00
    @Eugene1024 这样就是前端处理了,业务原因需要后端做处理。

    @TommyLemon 和第二种方法思路是一样的,APIJSON 我去看看学习下,谢谢喽
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1102 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:59 · PVG 06:59 · LAX 14:59 · JFK 17:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.