spring MVC +freemarker + easyui 实现sql查询和执行小工具总结
项目中,有时候线下不能方便的连接项目中的数据源时刻,大部分的问题定位和处理都会存在难度,有时候,一个小工具就能实时的查询和执行当前对应的数据源的库.下面,就本人在项目中实际开发使用的小工具,实时的介绍开发使用过程.首先看图:大概的操作界面,基本使用easyui组件实现,欢迎大家吐槽:
界面包含了基本的sql查询 和 sql执行的小功能,把查询和执行分开,也是为了后台实现的需要,以及权限控制的考虑,毕竟执行的操作,会影响到系统的数据问题.查询和执行的菜单,是用easyui的手风琴式的菜单处理的.两个菜单的界面都包含了执行按钮和重置按钮,输入sql的文本区域,和数据源<哪些db需要操作>的tab分开展示,以及文本下方的执行结果展示信息.
首先看下查询结果展示:
确定查询,可以展示当前sql的查询结果展示:结果采用分页展示,表头采用的是当前数据库的表的字段名称.
执行案例,就不展示图片信息了.会在执行的下方提示:当前的sql执行成功的条数. 下面重点分享开发实现过程:
1,采用spring MVC的架构处理,首先来看下controller的处理类,基本的spring mvc的配置信息,在这就不多描述了. 本类主要包含了四个控制方法,
a,main方法,主要跳转到工具管理主页面.
b,query方法,主要是sql查询的主方法,接收传输过来的sql语句,解析给交给数据库执行
c,queryDetail方法,主要是查询页面的分页查询方法,点击每一页的查询sql方法
d,excute方法,接收前台传输的执行sql,解析给数据库执行
/**
* 〈一句话功能简述〉<br>
* 〈功能详细描述〉
*
* @author lilin
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
@RequestMapping(value = "/tool")
@Controller
public class PmpTools { @Resource
private IPmpToolService pmpToolService; /**
*
* 功能描述: <br>
* 〈功能详细描述〉工具管理主页面
*
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/main")
public String main() {
return "/system/tools/main.ftl";
} /**
*
* 功能描述: <br>
* 〈功能详细描述〉sql的查询主方法
*
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping(value = "/query")
public String query(HttpServletRequest request) {
String findSql = request.getParameter("findSql");
String dataSource = request.getParameter("dataSource");
if (StringUtils.isNotEmpty(findSql) && StringUtils.isNotEmpty(dataSource)) {
String pageSql = pmpToolService.getQuerySqlByPage(findSql, 1, 1);
List<Map<String, Object>> list = pmpToolService.queryMapBySql(pageSql, dataSource);
if (list != null && !list.isEmpty()) {
request.setAttribute("column", list.get(0));
request.setAttribute("findSql", findSql);
request.setAttribute("dataSource", dataSource);
} else {
request.setAttribute("errorMessage", "未查到数据!");
}
}
return "/system/tools/queryDetail.ftl";
} /**
*
* 功能描述: <br>
* 〈功能详细描述〉
*
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@ResponseBody
@RequestMapping(value = "queryDetail")
public Object queryDetail(HttpServletRequest request) {
Map<String, Object> map = new HashMap<String, Object>();
String page = request.getParameter("page");
String rows = request.getParameter("rows");
int intPage = Integer.parseInt((page == null || page.equals("0")) ? "1" : page);
int number = Integer.parseInt((rows == null || rows.equals("0")) ? "10" : rows);
int start = (intPage - 1) * number + 1;
String findSql = request.getParameter("findSql");
String dataSource = request.getParameter("dataSource");
String totalSql = null;
List<Map<String, Object>> lists = null;
int totals = 0;
if (StringUtils.isNotEmpty(findSql)) {
try {
findSql = URLDecoder.decode(findSql, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("解析SQL报错!");
}
totalSql = pmpToolService.getTotalSql(findSql);
totals = pmpToolService.queryTotalNumBySql(totalSql, dataSource);
String pageSql = pmpToolService.getQuerySqlByPage(findSql, start, number);
lists = pmpToolService.queryMapBySql(pageSql, dataSource);
}
map.put("rows", lists);
map.put("total", totals);
return map;
} /**
*
* 功能描述: <br>
* 〈功能详细描述〉
*
* @param request
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@ResponseBody
@RequestMapping("excute")
public Object excute(HttpServletRequest request) {
String excuteSql = request.getParameter("excuteSql");
String dataSource = request.getParameter("dataSource");
String message = "";
Map<String, String> map = new HashMap<String, String>();
if (StringUtils.isNotEmpty(excuteSql)) {
try {
int flag = pmpToolService.exctueSql(excuteSql,dataSource);
message = "执行成功: " + flag + "行。";
} catch (RuntimeException e) {
message = "执行失败:" + e.getMessage();
}
}
map.put("message", message);
return map;
} }
2,页面主要是使用了freemaker+easyui的组件实现.主要页面包含如下:
下面分享每个页面的详细设计实现:
a,main页面:
<html>
<head>
<meta charset="UTF-8">
<title>工具页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<link rel="shortcut icon" href="http://www.suning.com/favicon.ico" type="image/x-icon"/>
<script type="text/javascript" src="${resRoot}/js/tool/tool.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#sqlSelect').tabs({
tools:'#tab-tools'
});
$('#sqlExcute').tabs({
onSelect:tool.excuteTabSelect
});
});
</script>
</head>
<body>
<div id="p" class="easyui-panel" title="SQL小工具" style="width:1420px;height:620px;">
<div class="easyui-accordion" style="width:100%;height:560px;">
<div title="SQL<>查询" style="overflow:auto;padding:10px;">
<div id="sqlSelect" style="width:99%;height:70px;">
<div title="WUPDB" style="text-align: center;">
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.query('uwpdb');"><span>执行</span></a>
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.clear('findSql');"><span>重置</span></a>
</div>
<div title="PMPDB" style="text-align: center;">
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.query('pmpdb');"><span>执行</span></a>
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.clear('findSql');"><span>重置</span></a>
</div>
</div>
<textarea rows="5" name="findSql" id="findSql" style="width:1380px;" placeholder="[输入查询sql]" class="commInput"></textarea>
<div id="detail" style="margin-top:4px;">暂无查询结果</div>
</div>
<div title="SQL<>执行" style="overflow:auto;padding:10px;">
<div id="sqlExcute" style="width:99%;height:70px;">
<div title="WUPDB" style="text-align: center;">
<div>
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.excute('uwpdb');"><span>执行</span></a>
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.clear('excuteSql');"><span>重置</span></a>
</div>
</div>
<div title="PMPDB" style="text-align: center;">
<div>
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.excute('pmpdb');"><span>执行</span></a>
<a href="javascript:void(0);" class="btn l mt10" onclick="tool.clear('excuteSql');"><span>重置</span></a>
</div>
</div>
</div>
<textarea rows="5" name="excuteSql" id="excuteSql" style="width:1380px;" placeholder="[输入执行sql]" class="commInput"></textarea>
<div id="excuteDetail" style="margin-top:4px;">暂无执行结果</div>
</div>
</div>
</div> </body>
</html>
b,queryDetail页面如下: 主要采用了easyui的datagrid的组件:用于分页查询嵌入
<script type="text/javascript">
$(document).ready(function(){
var findSql = "${findSql}";
var dataSource = "${dataSource}";
findSql = encodeURI(findSql);
$('#dataGrid').datagrid({
url: '${base}/tool/queryDetail.htm',
method: 'post',
title: '',
width: 1382,
height: 330,
fitColumns: true,
singleSelect: true,
columns:[[
{field:'RN',title:'序号'},
<#if column??>
<#list column?keys as col>
{field:'${col}',title:'${col}'},
</#list>
</#if>
{field:'',title:'',hidden:true}
]],
queryParams:{
findSql:findSql,
dataSource : dataSource
},
pagination:true,
onLoadError:function(){
$.messager.alert('警告','查询出错!','error');
},
onClickRow: function(rowIndex, rowData){
$('#dataGrid').datagrid('unselectRow', rowIndex);
}
});
}); </script>
<#if column??>
<table id="dataGrid"></table>
<#else>
<p style="color: red;padding:10px">无数据</p>
</#if>
3,页面的js操作,全部提取出来了到tool.js中:主要是查询和执行的方法:
Tool = function() { this.query = function(dataSource) {
var findSql = $.trim($('#findSql').val());
if (!findSql) {
$.messager.alert('警告', '请输入查询语句!', 'error');
return;
} else if (findSql.substring(0, 6) != 'select') {
$.messager.alert('警告', '查询语句请以select开头!', 'error');
return;
}
$.messager.confirm("操作提示", "您确定要执行操作吗?", function(data) {
if (data) {
$.ajax({
type : "post",
url : "${applicationName}/tool/query.htm",
dataType : "html",
async : true,
data : {
findSql : findSql,
dataSource : dataSource
},
success : function(html) {
$("#detail").empty();
$("#detail").html(html);
},
error : function() {
$("#detail").html("查询明细信息数据错误,请检查sql语句!");
}
});
}
});
}; this.excute = function(dataSource) {
var excuteSql = $.trim($('#excuteSql').val());
if (!excuteSql) {
$.messager.alert('警告', '请输入执行语句!', 'error');
return;
}
$.messager.confirm("操作提示", "您确定要执行操作吗?", function(data) {
if (data) {
$.ajax({
type : "post",
url : "${applicationName}/tool/excute.htm",
dataType : "json",
async : true,
data : {
excuteSql : excuteSql,
dataSource : dataSource
},
success : function(data) {
$("#excuteDetail").empty();
$("#excuteDetail").html(data.message);
},
error : function(e) {
$("#excuteDetail").html("执行sql语句错误,请检查sql语句!");
}
});
}
});
}; this.clear = function(textareaId) {
$('#' + textareaId).val('');
}; this.queryTabSelect = function(title,index){
$("#detail").html('暂时么有查询结果');
}; this.excuteTabSelect = function(title,index){
$("#excuteDetail").html('暂时么有执行结果');
};
};
var tool = new Tool();
4,service的类设计如下,接口就不做展示了,主要的方法展示:
/**
* 〈一句话功能简述〉<br>
* 〈功能详细描述〉
*
* @author lilin
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
@Service
public class PmpToolService implements IPmpToolService { @Resource
private IPmpToolDao pmpToolDao; @Override
public List<Map<String, Object>> queryMapBySql(String pageSql, String datasoure) {
return pmpToolDao.findMapBySql(pageSql, datasoure);
} @Override
public int queryTotalNumBySql(String totalSql, String datasoure) {
return pmpToolDao.queryTotalNumBySql(totalSql, datasoure);
} @Override
public int exctueSql(String sqlString, String datasource) {
return pmpToolDao.exctueSql(sqlString, datasource);
} @Override
public String getQuerySqlByPage(String findSql, int start, int maxRows) {
StringBuilder temp = new StringBuilder();
temp.append("SELECT * FROM ( SELECT ST.*, ROWNUMBER() OVER() AS RN FROM (");
temp.append(findSql);
temp.append(") AS ST)AS PT WHERE PT.RN BETWEEN ");
temp.append(start);
temp.append(" AND ");
temp.append(start + maxRows - 1);
return temp.toString();
} @Override
public String getTotalSql(String findSql) {
String temp = "";
if (findSql.indexOf("order") == -1) {
temp = findSql;
} else {
temp = findSql.substring(0, findSql.indexOf("order"));
}
return "select count(1) from (" + temp + ") as total";
}
}
5,dao层的方法设计和service的类似,主要是连接数据源的操作:
/**
* 〈一句话功能简述〉<br>
* 〈功能详细描述〉
*
* @author lilin
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
@Repository
public class PmpToolDao extends CommonDao implements IPmpToolDao { private static final String TOOL_SQL = "tool.sql"; @Override
public List<Map<String, Object>> findMapBySql(String pageSql, String datasource) {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("sql", pageSql);
if ("uwpdb".equals(datasource)) {
return getSoaDalClient().queryForList(TOOL_SQL, paramMap);
}
return getDalClient().queryForList(TOOL_SQL, paramMap);
} @Override
public int queryTotalNumBySql(String totalSql, String datasource) {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("sql", totalSql);
if ("uwpdb".equals(datasource)) {
return getSoaDalClient().queryForObject(TOOL_SQL, paramMap, Integer.class);
}
return getDalClient().queryForObject(TOOL_SQL, paramMap, Integer.class);
} @Override
public int exctueSql(String sqlString, String datasource) {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("sql", sqlString);
if ("uwpdb".equals(datasource)) {
return getSoaDalClient().execute(TOOL_SQL, paramMap);
}
return getDalClient().execute(TOOL_SQL, paramMap);
} }
6,最后就是sqlMap文件的相关sql,本组件主要是前台接收sql执行查询和执行操作,所以,sqlmap中的文件比较简单:
<?xml version="1.0" encoding="UTF-8" ?>
<sqlMap namespace="tool">
<sql id="sql">
<![CDATA[
${sql}
]]>
</sql>
</sqlMap>
到此为止,一个简单的sql查询和执行小工具就完成了,可以方便的进行当前的db的简单增删改查操作了,只要数据源用户的权限够,也能执行相关的DDL操作.
有个比较棘手的问题就是:当前的库的表中,有的字段信息存放的是xml格式的数据的时候,当前的组件展示会存在问题,不能正常的展示xml格式的文本数据,这个还在进一步的排查和解决中,希望有朋友能够指点,一起交流.这个暂时没有找寻到好的方法,之前打算采用字符替换的,也不能完全解决问题
spring MVC +freemarker + easyui 实现sql查询和执行小工具总结的更多相关文章
- SQL查询条件生成小工具
最近运维数据,经常遇到需要在sql条件中个In('',''....)个字符串的情况,于是在网上找了个小工具改造一下,先用着: 效果如图: using System; using System.Coll ...
- spring data jpa使用原生sql查询
spring data jpa使用原生sql查询 @Repository public interface AjDao extends JpaRepository<Aj,String> { ...
- Spring MVC+FreeMarker简介
最近做项目,刚接触到SpringMVC与FreeMarker框架,就简单介绍一下自己的理解,不正确的地方请大家指教!! 1.Spring MVC工作原理: 用户发送请求--->前端服务器去找相对 ...
- Spring MVC freemarker使用
什么是 FreeMarker? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具. 它不是面向最终用 ...
- spring mvc + freemarker优雅的实现邮件定时发送
1. spring mvc工程中引入相关freemarker\mail的包 如:pom.xml中加入类似 <dependency> <groupId>javax.mail< ...
- Spring MVC与easyui国际化
1.建立资源文件 在webapp下建立文件夹language,在其中再添加file,命名分别为language.properties,language_en.properties,language_z ...
- SQL查询语句执行的逻辑顺序
一.简介 大家都知道SELECT语句是用来查询数据表中的数据的,构成SELECT语句的还有各种元素(where.from.group by等),不同元素又代表了不同的处理逻辑,那么这些元素在执行查询时 ...
- SQL 查询的执行顺序
SELECT语句的完整语法如下 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN & ...
- SQL查询语句执行流程
msyql执行流程 你有个最简单的表,表里只有一个 ID 字段,在执行下面这个查询语句时:: select * from T where ID=10: 我们看到的只是输入一条语句,返回一个结果,却不知 ...
随机推荐
- 实验6 Bezier曲线生成
1.实验目的: 了解曲线的生成原理,掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法. 2.实验内容: (1) 结合示范代码了解曲线生成原理与算法实现,尤其是Bezier ...
- chrome模拟微信
这里有一个模拟器,既可以设置模拟很多型号的手机设备,也可以伪造你想要的HTTP_USER_AGENT.选择USER_AGENT,选other,微信的HTTP_USER_AGENT是: 在iPhone下 ...
- JS 作业
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 路飞学城Python-Day150
最近由于在忙别的事情,所以路飞的课程就往后延期了,感觉很难受,不过我还是依然坚持学下去,必须的 最近在忙的事情 1.进入了数据分析行业,需要学习更多的知识 2.开始对数据收集负责,写各种爬虫 3.对数 ...
- 【真·干货】MySQL 索引及优化实战
热烈推荐:超多IT资源,尽在798资源网 声明:本文为转载文章,为防止丢失所以做此备份. 本文来自公众号:GitChat精品课 原文地址:https://mp.weixin.qq.com/s/6V7h ...
- 基于 SpringMVC——web.xml基本配置
<!--声明应用范围内的初始化参数--> <context-param> <param-name>contextConfigLocation</param-n ...
- adb简单使用
一.基本命令 1.查看目前连接的设备/虚拟器的状态 adb devices
- springmvc上传操作
创建虚拟目录 配置tomcat的配置文件server.xml 在真实路径中放置一个图片 启动服务器: 直接可以通过配置的虚拟路径来访问真实路径中的图片 所以 我们在做图片上传的操作的时候 就可 ...
- “王者对战”之 MySQL 8 vs PostgreSQL 10
既然 MySQL 8 和 PostgreSQL 10 已经发布了,现在是时候回顾一下这两大开源关系型数据库是如何彼此竞争的. 在这些版本之前,人们普遍认为,Postgres 在功能集表现更出色,也因其 ...
- 洛谷—— P1262 间谍网络
https://www.luogu.org/problem/show?pid=1262 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A ...