效果,首先打开HQL的参数日志,
这种也要看hibernate版本,5.1及其一下用这个,以上的可以用新的方式,也可以自己搜索打开HQL的参数日志的方法有几种方式
<logger category="org.hibernate.type.descriptor.sql.BasicBinder" use-parent-handlers="false"><level name="TRACE"/> <handlers><handler name="HIBERNATEFILE"/></handlers></logger>
或者使用SPY插件,我这个是jboss自带,
package util;import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;public class MesLogHandel {public static void main(String[] args) {String select=" select * ";HashSet<String> sqls=new HashSet<>();String filePath ="F:\\SoftWare\\wildfly-10.1.0.Final-V6\\standalone\\log\\server.log";String sqldemo=null;//记录所有sql信息List<String> allSqls=new ArrayList<>();List<String> subSqls=new ArrayList<>();try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "GB2312"))) {String line;String sqltext=null;//线程mapMap<String,String> threadMaps=new HashMap<>();//线程sqlMapMap<String,String> sqlMaps=new HashMap<>();//线程参数集合mapMap<String,List<Object>> listMaps=new HashMap<>();//线程参数计数Map<String,Integer> countMaps=new HashMap<>();String thread=null;String paramstring=null;String lastSql=null;while ((line = reader.readLine()) != null) {// 逐行读取并处理if (line.contains("prepareStatement(")){//获取sql语句处理sqltext=line.split("prepareStatement\\(")[1];sqltext=sqltext.substring(0,sqltext.length()-1);int count= countPlaceholders(sqltext);if (count>0){thread=line.split(" java:")[0].split("jdbc.spy] ")[1];threadMaps.put(thread,thread);countMaps.put(thread,countPlaceholders(sqltext));sqlMaps.put(thread,sqltext);List<Object> parmes=new ArrayList<>();listMaps.put(thread,parmes);}else{allSqls.add(sqltext);subSqls.add(sqltext);//handleSql(sqltext,sqls);}}else if (line.contains("[PreparedStatement] set")){//获取参数处理thread=line.split(" java:")[0].split("jdbc.spy] ")[1];if(threadMaps.containsKey(thread)){paramstring=line.split("PreparedStatement")[1];if (handleValue(paramstring,thread,listMaps,countMaps,sqlMaps)){//参数获取完毕,清空线程所有信息try {lastSql=HqlSqlGenerator.generateSql(sqlMaps.get(thread),listMaps.get(thread));//异常此sql作废,后续不做处理allSqls.add(lastSql);if (lastSql.contains("select * from (")&&lastSql.contains(") where rownum")){int i=lastSql.indexOf(") where rownum");lastSql=lastSql.substring(16,i);//sqltext=sqlBuilder.toString().replaceAll("select * from \\(","").replaceAll("\\) where rownum <= ?","");}//handleSql(lastSql,sqls);if(lastSql.indexOf(" from ")>0){int pos=lastSql.indexOf(" from ");lastSql=select+lastSql.substring(pos,lastSql.length());}subSqls.add(lastSql);}catch (Exception e){System.out.println("作废sql:"+lastSql);System.out.println(e);}listMaps.remove(thread);countMaps.remove(thread);sqlMaps.remove(thread);threadMaps.remove(thread);}}}}} catch (Exception e) {e.printStackTrace();System.out.println("报错"+sqldemo);System.out.println("Error reading file: " + filePath);}//存储原始sqlString cfilePath = "E:\\mesLogSql.txt";//存储简化后的sql,去掉外层分页和select 所有选项改为select * ,多表查询时,可能会一起去掉了,但是字段都查太长了String cfilePath1 = "E:\\mesLogSql1.txt";try (BufferedWriter writer = new BufferedWriter(new FileWriter(cfilePath))) {for (String sql:allSqls){//System.out.println(sql);if (handleFilter(false,sql)){writer.write(sql+";");writer.newLine();}}} catch (IOException e) {System.err.println("创建文件或写入文件时出错: " + e.getMessage());}try (BufferedWriter writer = new BufferedWriter(new FileWriter(cfilePath1))) {for (String sql:subSqls){//System.out.println(sql);if (handleFilter(false,sql)){writer.write(sql+";");writer.newLine();}}} catch (IOException e) {System.err.println("创建文件或写入文件时出错: " + e.getMessage());}}public static boolean handleFilter(boolean isfiter,String line){boolean istrue=true;if (isfiter){if (line.contains("COM_TASK_HIS")||line.contains("COM_TASK_TIMESTAPM")||line.contains("COM_TASK")){istrue=false;}}return istrue;}/*** 处理参数信息* @param value* @param thread* @param listMaps* @param countMaps* @param sqlMaps* @return*/public static boolean handleValue(String value,String thread,Map<String,List<Object>> listMaps, Map<String,Integer> countMaps,Map<String,String> sqlMaps){boolean isOver=false;try {List<Object> params= listMaps.get(thread);int i=value.indexOf("(");int j=value.indexOf(",");String colVaues=value.substring(j+1,value.length()-1).trim();int count=Integer.valueOf(value.substring(i+1,j));if (count==countMaps.get(thread)){isOver=true;}if (value.contains("setString")){params.add(colVaues);}else if (value.contains("setLong")){params.add(Long.valueOf(colVaues));}else if (value.contains("setInt")){params.add(Integer.valueOf(colVaues));}else if (value.contains("setBigDecimal")){params.add(new BigDecimal(colVaues));}else if (value.contains("setTimestamp")){params.add(colVaues);}else if (value.contains("setBytes")){params.add(colVaues);}else if (value.contains("setNull")){params.add(colVaues);}else {System.out.println("特殊类型"+value);params.add(null);}listMaps.put(thread,params);}catch (Exception e){System.out.println("参数获取报错:"+value);System.out.println(e);}return isOver;}/*** 统计占位符号?的数量* @param hql* @return*/public static int countPlaceholders(String hql) {if (hql == null) {return 0;}Pattern pattern = Pattern.compile("\\?");Matcher matcher = pattern.matcher(hql);int count = 0;while (matcher.find()) {count++;}return count;}
}