我一共建立了3个VO, V$sqlarea(其实也是实体,包含rownum)V$sqlareaListCountVo 和 V$sqlareaVo(不包含rownum)java
直接代码:Daosql
@Query(value=" SELECT \r\n"+ " t.SQL_ID, \r\n"+ " t.ELAPSED_TIME, \r\n"+ " t.EXECUTIONS, \r\n"+ " t.LAST_ACTIVE_TIME, \r\n"+ " t.CPU_TIME \r\n"+ " FROM v$sqlarea t \r\n"+ " WHERE \r\n" + " t.PARSING_SCHEMA_NAME = :parsingSchemaName \r\n" + " AND t.EXECUTIONS >= :executions \r\n" + " AND t.LAST_ACTIVE_TIME >= :startActiveTime \r\n" + " AND t.LAST_ACTIVE_TIME < :lastActiveTime \r\n" + " AND t.ELAPSED_TIME >= :elapsedTime \r\n" + " AND t.CPU_TIME >= :cpuTime " , countQuery=" SELECT \r\n"+ " count(t.SQL_ID) \r\n"+ " FROM v$sqlarea t \r\n"+ " WHERE \r\n" + " t.PARSING_SCHEMA_NAME = :parsingSchemaName \r\n" + " AND t.EXECUTIONS >= :executions \r\n" + " AND t.LAST_ACTIVE_TIME >= :startActiveTime \r\n" + " AND t.LAST_ACTIVE_TIME < :lastActiveTime \r\n" + " AND t.ELAPSED_TIME >= :elapsedTime \r\n" + " AND t.CPU_TIME >= :cpuTime ",nativeQuery = true ) public Page<Object[]> findTopSQLS2(@Param("parsingSchemaName")String parsingSchemaName, @Param("executions")Number executions, @Param("startActiveTime")Date startActiveTime, @Param("lastActiveTime")Date lastActiveTime, @Param("elapsedTime")Number elapsedTime, @Param("cpuTime")Number cpuTime, Pageable pageable);
由于是自定义实体因此我使用Object[ ]进行接收数据数据库
下面看下个人service层,多条件是我自定义的,感受比较low,若是不是自定义实体咱们直接能够调用JPA接口,使用example参数进行条件构造了,咱们使用Object[ ]接收参数,而后咱们使用EntityUtils中castEntity()方法进行转换你想要的实体类,数组
而后之因此定义V$sqlareaListCountVo是由于我controller中须要pages.getTotalElements()这个参数,这个参数是数据总数量,分页须要他,sqlareaListCountVo中有三个参数一个是 集合Vo 另外一个就是 里面多了一个rownum属性的集合Vo,还有一个即是数据总数,下面我会讲为何我建两个Vo【主要由于oracle(我使用的是oracle数据库),分页第一次查询的时候,没有rownum这个数据字段,可是第一次以后就会有这个字段,因此我定义了两个Vo一个有rownum,另外一个没有rownum,当第一次进来我就使用没有rownum的那个Vo,第一次以后我就会使用另外一个包含rownum属性的Vo】MySQL应该不会出现这样的状况,oracle
而后就是排序,前台传asc desc,可是后台不能这么写,因此我使用了三元运算符app
order.equals("asc") ? Sort.Direction.ASC : Sort.Direction.DESCide
避免使用if else显得代码累赘 =-= 其实如今我都感受个人代码很累赘。。。。。。。。。函数
/** * 查询topSQL */ @Override public V$sqlareaListCountVo findTopSQL(Integer pageNum, Integer pageSize, ReqV$sqlarea sql) throws ParseException { V$sqlarea v$sqlarea = new V$sqlarea(); ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("indicatorsName", ExampleMatcher.GenericPropertyMatchers.contains()); Example<V$sqlarea> example = Example.of(v$sqlarea, matcher); // 表空间名称 String tableSpaseName = "C##DBAAS"; // sql执行次数 Number executions = sql.getExecutions(); // 最新执行时间 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date startActiveTime = sql.getStartActiveTime(); Date lastActiveTime = sql.getLastActiveTime(); // 执行总时间(微秒) Number elapsedTime = sql.getElapsedTime(); // sql执行所占用cpu的时间(微秒) Number cpuTime = sql.getCpuTime(); // if (null == tableSpaseName) { // throw new CustomerException(1001, "表空间名称不能为空"); // } if (null == executions) { executions = 0; } else if (executions.intValue() < 0) { throw new CustomerException(1001, "执行次数不能为负数"); } if (null == lastActiveTime) { lastActiveTime = new Date(); } if (null == startActiveTime) { startActiveTime = sdf.parse("0001-01-01 01:01:01"); } if (null == elapsedTime) { elapsedTime = 0; } else if (elapsedTime.intValue() < 0) { throw new CustomerException(1001, "执行次数不能为负数"); } if (null == cpuTime) { cpuTime = 0; } else if (cpuTime.intValue() < 0) { throw new CustomerException(1001, "执行次数不能为负数"); } String order = sql.getOrder(); Pageable pageable = PageRequest.of(pageNum, pageSize, order.equals("asc") ? Sort.Direction.ASC : Sort.Direction.DESC, sql.getSortName()); Page<Object[]> pages = v$sqlareaDao.findTopSQLS2(tableSpaseName, executions, startActiveTime, lastActiveTime,elapsedTime, cpuTime, pageable); System.out.println(pages.getTotalElements()); List<V$sqlarea> list1 = null; List<V$sqlareaVo> list2 = null; V$sqlareaListCountVo v$sqlareaListCountVo = new V$sqlareaListCountVo(); if (pageNum != 0) { list1 = EntityUtils.castEntity(pages.getContent(), V$sqlarea.class, new V$sqlarea()); v$sqlareaListCountVo.setCount(pages.getTotalElements()); v$sqlareaListCountVo.setList(list1); return v$sqlareaListCountVo; } else { list2 = EntityUtils.castEntity(pages.getContent(), V$sqlareaVo.class, new V$sqlareaVo()); v$sqlareaListCountVo.setCount(pages.getTotalElements()); v$sqlareaListCountVo.setListVo(list2); return v$sqlareaListCountVo; } }
下面是个人EntityUtils类code
package com.befery.oams.util; 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 zhangxuewei * */ public class EntityUtils { private static Logger logger = LoggerFactory.getLogger(EntityUtils.class); /** * 将数组数据转换为实体类 * 此处数组元素的顺序必须与实体类构造函数中的属性顺序一致 * * @param list 数组对象集合 * @param clazz 实体类 * @param <T> 实体类 * @param model 实例化的实体类 * @return 实体类集合 */ public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz, Object model) { List<T> returnList = new ArrayList<T>(); if (list.isEmpty()) { return returnList; } //获取每一个数组集合的元素个数 Object[] co = list.get(0); //获取当前实体类的属性名、属性值、属性类别 List<Map> 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<T> 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 Object getFieldValueByName(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 List<Map> getFiledsInfo(Object model) { Field[] fields = model.getClass().getDeclaredFields(); List<Map> 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; } }
注意:映射自定义实体类中,必须有构造函数,而且构造函数中的参数要 和 你sql中查询的字段顺序必须保持一致,这样才不会出错,orm
而后看下个人controller层,在这里我也是没有办法,进行判断两个Vo中哪一个有值我便返回哪个
/** * 查询TopSQL * @author zhangxuewei * @param pageNum * @param pageSize * @param sql * @return * @throws ParseException */ @GetMapping(value = "/list") @ResponseBody public PageResult selectTopSQLUntreated(@RequestParam(value = "pageNumber", defaultValue = "0")Integer pageNum,@RequestParam(value = "pageSize", defaultValue = "2") Integer pageSize,ReqV$sqlarea sql) throws ParseException { V$sqlareaListCountVo vo = topSQLService.findTopSQL(pageNum-1, pageSize, sql); PageResult page = new PageResult(); page.setTotal(vo.getCount()); if(null == vo.getList()) { page.setRows(vo.getListVo()); return page; }else { page.setRows(vo.getList()); return page; } }