mybatis处理一对多时性能太低的解决方法探讨
一、前言
在开发的时候为了图方便和结构清晰,我们往往会在项目中使用@Many注解来实行实体类内部一对多的数据获取,如
@Select("...") @Results({ @Result(property = "XXXX", javaType = List.class, many = @Many(select = "XXXX", fetchType = FetchType.EAGER), column = "XXXX") }) List<EntityA> getXXXXEntities(QueryParam param);
这种写法在数据量增加至千,万级别时,响应时间会明显增长(很容易就能达到十几秒以上),这很明显不能直接应用到生产中,分析: 发起查询时,先查出@select的结果封装成实体类对象,再根据加载策略(fetchType = FetchType.EAGER,这里是即时加载),针对查到的每个实体类对象去加载其内部的List类型的一对多的值,这样针对每个实体类对象都需要额外的对数据库重新发起一次查询请求,这样一来速度自然就会下降(大部分时间都花费在与数据库建立连接,发送查询请求,获取查询结果 上面了)
二、解决办法
减少向数据库发起的请求次数
情景1
一对多(实体类 对 String)
//实体类 public class Department{ ... List<String> employees; //员工姓名 public void setEmployeesAll(String employeeAll){ employees = employeeAll.split("@"); } } @Select("select dep.x1,dep.x2...,dep.x3," + "(select GROUP_CONCAT(employee.name ORDER BYemployee.name ASC SEPARATOR @) " + "from employee " + "where employee.department_id = department.department_id " + "GROUP BY employee.department_id LIMIT 1) " + "as employeeAll from department") List<Department> getDepartments();
解读:发起一次查询,查出所有需要的信息,在setter里面将信息进行拆分装配,可以有效减少响应时间。
情景2
实体类 对 实体类
//实体类 public class Employee{ ...} public class Department{ ... List<Employee> employees; //员工姓名 public void setEmployeesAll(String employeeAll){ String[] employeeInfos= employeeAll.split("@"); if(employeeInfos != null && employeeInfos.length > 0){ employees = new ArrayList<Employee>(employeeInfos.length/(员工类的信息个数)); for(int i=0;i<employeeInfos.size();){ Employee temp = new Employee(); temp.setXX0(employeeInfos[i++]); temp.setXX1(employeeInfos[i++]); temp.setXX2(employeeInfos[i++]); ... employees.add(temp); } } } }
解读:思路同情景1,发起一次请求查出所有信息,在setter中进行拆分装配。sql查询不再多写了,基本一致的。(GROUP_CONCAT真是个好东西)
最后
如果你有更好的思路或者方法,欢迎指教。
上一篇:
IDEA上Java项目控制台中文乱码