JPA 复杂查询和MYSQL性能优化

    实验室大佬选用 SpringData JPA 作为 项目的持久层框架,让对于我一个菜鸡来说苦苦挣扎了许久,踩了N多坑。现在项目基本完成了,终于松了口气,希望不要再出现bug。

JPA 优点:

    对于单表操作是非常友好的,JPA框架给我们封装好了很多操作数据库的方法,这时候一般都只需要调用这些方法就能完成简单的增删改查操作,不需要自己手写sql,使用起来非常的方便。

 但是对于复杂多表关联查询返回自定义实体类时,返回前端数据时往往是需要多表关联查询组装成一个新的实体类,所以使用起来没有那么友好了。在这里操作往往还要使用JPA的分页插件,集成这些也容易出现bug。下面我在项目中用到多表查询返回自定义实体类的两种方式

方式一: 自己定义一个实体类用来接受查询到的字段,然后通过new 全限定类名,使用的是hql语句

  方式二: 上面的情况不能满足需求,当数据量很大sql查询太慢,需要自己手写原生sql来优化查询速度,这时候也不能使用jpa中的分页插件,还需要自己手动实现分页。注意,使用原生sql多表查询得到的是object型的数据,需要进行转换


下面是将object型数组转成所需实体类类型的数组

package com.grid.monitor.base.utils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* @Author AflyStart

* @Description:

* @Date: Created in 15:02 2020/11/30

*/

public class EntityUtils {

private static Loggerlogger = LoggerFactory.getLogger(EntityUtils.class);

    /**

    * 将数组数据转换为实体类

    * 此处数组元素的顺序必须与实体类构造函数中的属性顺序一致

    *

    * @param list          数组对象集合

    * @param clazz          实体类

    * @param             实体类

    * @param model          实例化的实体类

    * @return 实体类集合

    */

    public static ListcastEntity(List list, Class clazz, Object model) {

List returnList =new ArrayList();

        if (list.isEmpty()) {

return returnList;

        }

//获取每个数组集合的元素个数

        Object[] co = list.get(0);

        //获取当前实体类的属性名、属性值、属性类别

        List attributeInfoList =getFiledsInfo(model);

        //创建属性类别数组

        Class[] c2 =new Class[attributeInfoList.size()];

        //如果数组集合元素个数与实体类属性个数不一致则发生错误

        if (attributeInfoList.size() != co.length) {

return returnList;

        }

//确定构造方法

        for (int i =0; i < attributeInfoList.size(); i++) {

c2[i] = (Class) attributeInfoList.get(i).get("type");

        }

try {

for (Object[] o : list) {

Constructor constructor = clazz.getConstructor(c2);

                returnList.add(constructor.newInstance(o));

            }

}catch (Exception ex) {

logger.error("实体数据转化为实体类发生异常:异常信息:{}", ex.getMessage());

            return returnList;

        }

return returnList;

    }

/**

    * 根据属性名获取属性值

    *

    * @param fieldName 属性名

    * @param modle    实体类

    * @return 属性值

    */

    private static ObjectgetFieldValueByName(String fieldName, Object modle) {

try {

String firstLetter = fieldName.substring(0, 1).toUpperCase();

            String getter ="get" + firstLetter + fieldName.substring(1);

            Method method = modle.getClass().getMethod(getter, new Class[]{});

            Object value = method.invoke(modle, new Object[]{});

            return value;

        }catch (Exception e) {

return null;

        }

}

/**

    * 获取属性类型(type),属性名(name),属性值(value)的map组成的list

*

    * @param model 实体类

    * @return list集合

    */

    private static ListgetFiledsInfo(Object model) {

Field[] fields = model.getClass().getDeclaredFields();

        List list =new ArrayList(fields.length);

        Map infoMap =null;

        for (int i =0; i < fields.length; i++) {

infoMap =new HashMap(3);

            infoMap.put("type", fields[i].getType());

            infoMap.put("name", fields[i].getName());

            infoMap.put("value", getFieldValueByName(fields[i].getName(), model));

            list.add(infoMap);

        }

return list;

    }

}

你可能感兴趣的:(JPA 复杂查询和MYSQL性能优化)