【Java与Python实现】最实际与高效生成数据库高级声明式SQL脚本神器研发
一、 简介
1.1前言
1.2作用
二、 实现方式与原理
2.1实现方式
2.2原理
三、 体系与图解
3.1创建表与插数据脚本
3.2添加或修改表脚本
3.3删除表脚本
3.4删除与创建索引脚本
3.5删除与创建序列脚本
3.6删除与创建存储过程脚本
3.7删除与创建视图脚本
四、 开发环境与工具
4.1Nexu*仓库
4.2 Eclipse
4.3 Tomcat
4.4 JDK
4.5Maven
4.6ER-Ermaster
五、 使用技术体系实现
5.1前端UI
5.1.1 BootStrap
5.1.2 Font Awesome
5.1.3 jQuery
5.1.4 jQuery高亮插件
5.2.5 LayerUI与jBox弹窗技术
5.2.6 colResizable拖拽插件
5.2.7 bumpyText插件
5.2框架与技术
5.2.1 Servlet3.x
5.2.2 SpringMVC
5.2.3 ORM
5.2.4 POI与JXL
5.2.5 JSON
六、 代码实现与效果
6.1Servlet3.x+jdbc实现
6.1.1Pojo
6.1.2Service
6.1.3Util
6.1.4Controler
6.1.5其他说明
6.1.6效果
6.2SpringMVC+JdbcTemplate实现
6.2.1Pojo
6.2.2Service
6.2.3DAO
6.2.4Controler
6.2.5前端技术
6.2.6Java的JXL实现与Python的xlrd实现
6.2.7Util底层封装代码
6.2.8其他说明
6.2.9功能与效果
七、 个人总结
7.1为什么要总结
7.2为什么记录笔记
7.3其他说明
一、简介
1.1前言
1、由于最近工作一直用Oracle,故对Oracle数据库研究为对象。
2、根据工作业务需求实际情况进行功能研发。为什么要开发呢?因为在数据库升级或者迁移的时候,为了保证不同环境不同数据库数据保持同步,故数据库SQL脚本非常作用。比如:数据库主脚本,副脚本,增量脚本。
3、 什么是主脚本、副脚本、增量脚本呢?
3.1、主脚本指数据库表或存储过程,视图脚本,序列等脚本。
3.2、副脚本指必须执行主脚本之后才执行的脚本。换句话说在没执行主键脚本的情况下,副脚本执行之后会回滚事务失败。
3.3、增量脚本指在执行主脚本或副脚本之后,根据需求对某个表添加/修改约束(主外键约束,长度约束等),添加/修改字段/添加数据等情况对数据库结构改变处理的一种行为脚本。
1.2作用
1、 快速产出自定义规则需要的SQL脚本。
2、减少人工编写SQL脚本出错率问题,完全通过程序检测SQL准确性。
3、帮助开发人员提高SQL编写效率,减少人工编写SQL开发成本问题。
4、帮助开发人员节约时间,同时避免繁琐不必要编写SQL的工作。
二、实现方式与原理
2.1实现方式
1、实现方式分:正向与逆向实现。什么是正向与逆行呢【是否有鸡还是有蛋,先后道理同等】
2、正向方式:首先把设计好数据库表文档,把所有表的字段属性配置到EXCEL或者CSV格式的文件通过JXL/POI技术去读取文件的字段,再通过其他技术一系列程序处理之后生成所需要的SQL脚本。
3、逆向方式:首先有数据库表,然后通过ORM持久化技术连接数据库再读取表的字段等属性出来,再通过其他技术一系列程序处理之后生成所需要的SQL脚本。
2.2原理
对数据库软件内置核心表或视图查询出来存储用户行为表结构所有属性信息,对此属性结构信息进行分析与组装所需要SQL脚本。
三、体系与图解
--第一种方法: 查询dba_tab_columns
select COLUMN_NAME,DATA_TYPE,DATA_LENGTH from dba_tab_columns where table_name =upper('表名') order by COLUMN_NAME
--这种方法需要有DBA权限
--第二种方法: 查询 user_tab_cols
select COLUMN_NAME,DATA_TYPE,DATA_LENGTH from user_tab_cols where table_name=upper('表名')
order by COLUMN_NAME
--这种方法只能查找当前用户下的表
--第三种方法: 查询ALL_TAB_COLUMNS
select distinct COLUMN_NAME,DATA_TYPE,DATA_LENGTH
from ALL_TAB_COLUMNS
WHERE TABLE_NAME= upper('表名')
--这种方法可以查询所有用户下的表
---------------------------补充-------------------------------------------------------------
--增加cw_srcbpb表字段
alter table cw_srcbpb add (SRCBPB_RJBPBL varchar2(100) );
--修改cw_srcbpb表字段
alter table cw_srcbpb modify (SRCBPB_RJBPBL number(30,3) );
--Oracle查看所有表和字段
--获取表:
select table_name from user_tables; --当前用户的表
select table_name from all_tables; --所有用户的表
select table_name from dba_tables; --包括系统表
select table_name from dba_tables where owner='LBSP'; --获取用户***所拥有的表这里的用户名要记得是用大写的。
-- 获取表字段:其实这里是根据用户的权限来获取字段的属性(表名要大写)
select * from user_tab_columns where Table_Name='用户表';--获取用户表的所有字段还有字段的属性。
select * from all_tab_columns where Table_Name='用户表';--获取用户表的所有字段还有字段的属性。所属用户是***
select * from dba_tab_columns where Table_Name='用户表';--获取用户表的所有字段还有字段的属性。所属用户是***
--获取表注释:
select * from user_tab_comments
--user_tab_comments:table_name,table_type,comments
--相应的还有dba_tab_comments,all_tab_comments,这两个比user_tab_comments多了ower列。
--获取字段注释:
select * from user_col_comments
--user_col_comments:table_name,column_name,comments
--相应的还有dba_col_comments,all_col_comments,这两个比user_col_comments多了ower列。
--查询出用户所有表的索引
select * from user_indexes
--查询用户表的索引(非聚集索引):
select * from user_indexes where uniqueness='NONUNIQUE'
--查询用户表的主键(聚集索引):
select * from user_indexes where uniqueness='UNIQUE'
--查询表的索引
select t.*,i.index_type from user_ind_columns t,user_indexes i where t.index_name = i.index_name and
t.table_name='NODE'
--查询表的主键
select cu.* from user_cons_columns cu, user_constraints au where cu.constraint_name = au.constraint_name and
au.constraint_type = 'P' AND cu.table_name = 'NODE'
--查找表的唯一性约束(包括名称,构成列):
select column_name from user_cons_columns cu, user_constraints au where cu.constraint_name=au.constraint_name and
cu.table_name='NODE'
--查找表的外键
select * from user_constraints c where c.constraint_type = 'R' and c.table_name='STAFFPOSITION';
--查询外键约束的列名:
select * from user_cons_columns cl where cl.constraint_name = '外键名称';
--查询引用表的键的列名:
select * from user_cons_columns cl where cl.constraint_name = '外键引用表的键名';
declare
iCnt number := 0;
begin
select count(*) into iCnt from user_tables where lower(table_name) = lower('T_CLASS');
if iCnt = 0 then -- 如果查询不到这个表就创建这个表
execute immediate 'create table T_CLASS
(
CLASS_ID NUMBER(11) NOT NULL ,
CLASS_NAME VARCHAR2(50) NOT NULL,
CLASS_NO VARCHAR2(30) NOT NULL,
CLASS_NUM NUMBER(10) NOT NULL
)';
execute immediate 'comment on table T_CLASS is ''班级表''';
execute immediate 'alter table T_CLASS add constraint PK_CLASS_ID primary key (CLASS_ID)' ;
execute immediate 'comment on column T_CLASS.CLASS_NAME is ''班级名称''';
execute immediate 'comment on column T_CLASS.CLASS_NO is ''班级编号''';
execute immediate 'comment on column T_CLASS.CLASS_NUM is ''班级人数''';
end if;
end;
/
commit
declare
iCnt number := 0;
begin
select count(*) into iCnt from user_tables where lower(table_name) = lower('T_STUDENT');
if iCnt = 0 then -- 如果查询不到这个表就创建这个表
execute immediate 'create table T_STUDENT
(
USER_ID NUMBER(11) NOT NULL ,
ID_CARD_CODE VARCHAR2(50) NOT NULL,
USER_NAME VARCHAR2(30) NOT NULL,
PASS_WORD VARCHAR2(30) NOT NULL,
AGE NUMBER(10) NOT NULL,
ADDRESS VARCHAR2(255) ,
CREATE_TIME DATE
)';
execute immediate 'comment on table T_STUDENT is ''学生用户表''';
execute immediate 'alter table T_STUDENT add constraint PK_USER_ID primary key (USER_ID)' ;
execute immediate 'comment on column T_STUDENT.ID_CARD_CODE is ''身份证编号''';
execute immediate 'comment on column T_STUDENT.USER_NAME is ''用户名''';
execute immediate 'comment on column T_STUDENT.PASS_WORD is ''用户密码''';
execute immediate 'comment on column T_STUDENT.AGE is ''年龄''';
execute immediate 'comment on column T_STUDENT.ADDRESS is ''地址''';
execute immediate 'comment on column T_STUDENT.CREATE_TIME is ''创建时间''';
end if;
end;
/
commit
--删除T_STUDENT的唯一索引
declare
iCnt number := 0;
begin
select count(*) into iCnt from user_ind_columns where lower(index_name) = lower('stu_idx_card_code') and lower(table_name)=lower('T_STUDENT');
if iCnt > 0 then
execute immediate 'drop index stu_idx_card_code ';
end if;
end;
/
--对学生表的身份证ID加唯一索引ID_CARD_CODE
declare
iCnt number := 0;
begin
select count(*) into iCnt from user_ind_columns where lower(index_name) = lower('stu_idx_card_code') and lower(table_name)=lower('T_STUDENT');
if iCnt = 0 then
execute immediate 'create unique index stu_idx_card_code on T_STUDENT(id_card_code)';
end if;
end;
/
----------------------------------------------------------------------------------
--删除学生表序列Id
declare
iCount integer;
begin
select count(*) into iCount from user_sequences where upper(sequence_name)=upper('SQ_T_STUDENT');
if iCount > 0 then
execute immediate 'drop sequence SQ_T_STUDENT ';
end if;
end;
/
--创建学生表序列Id
declare
iCount integer;
begin
select count(*) into iCount from user_sequences where upper(sequence_name)=upper('SQ_T_STUDENT');
if iCount = 0 then
execute immediate
'create sequence SQ_T_STUDENT
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
nocache';
end if;
end;
/
--传统创建视图脚本
CREATE OR REPLACE VIEW V_STUDENT AS
SELECT
user_id,
user_name ,
pass_word ,
age,
create_time,
id_card_code
FROM T_STUDENT
WITH READ ONLY; --只读视图
--声明式删除视图
declare
iCnt number := 0;
begin
SELECT count(*) into iCnt FROM all_views where upper(view_name)=upper('V_STUDENT');
if iCnt > 0 then
execute immediate 'drop VIEW V_STUDENT ';
end if;
end;
/
--声明式创建视图脚本,WITH READ ONLY表示只读视图
declare
iCnt number := 0;
begin
SELECT count(*) into iCnt FROM all_views where upper(view_name)=upper('V_STUDENT');
if iCnt = 0 then
execute immediate 'CREATE OR REPLACE VIEW V_STUDENT AS
SELECT
user_id,
user_name ,
pass_word ,
age,
create_time,
ID_CARD_CODE
FROM T_STUDENT
WITH READ ONLY
';
end if;
end;
/
/*
* @Description:
* declare 代表是声明变量,输入参数/输出参数的SQL关键字
* begin 表示开始执行
* execute immediate 立刻执行
* end if 结束if语句
* end 结束开始语句
* / 斜杠代表结束SQL语句
* into代表是赋值给某个变量/是插入SQL语句的关键字
* then然后的意思
* comment on table与comment on column 对表和列进行添加备注说明
* primary key 主键字
* http://www.jb51.net/article/45539.htm
*
*/
--添加字段的语法:alter table tablename add (column datatype [default value][null/not null],….);
--修改字段的语法:alter table tablename modify (column datatype [default value][null/not null],….);
--删除字段的语法:alter table tablename drop (column);
---==================================(删除/清空)表脚本=====================================
declare
iCnt number := 0;
begin
select count(*) into iCnt from user_tables where lower(table_name) = 't_user_info'; --根据表进行查询
if iCnt = 1 or iCnt>0 then -- 如果查询到(删除/清空)表
execute immediate 'drop table t_user_info'; --删除表,表结构和数据一起清空
--execute immediate 'truncate table t_user_info'; --清除表,表结构和数据一起清除
--execute immediate 'delete from t_user_info'; --删除表数据,可以根据条件删除
end if;
end;
/
/*
---****************************************查询索引信息表 ****************************************
select table_name,constraint_name,constraint_type from user_constraints where table_name='大写的表名' ; --用户约束
select table_name,constraint_name,constraint_type from dba_constraints where table_name='大写的表名' ; --dba约束
select * from USER_INDEXES where table_name = '大写的表名'; --用户索引upper(table_name)=upper('表名');
select * from ALL_INDEXes where table_name = '大写的表名'; --所有索引
---****************************************查询索引信息表 ****************************************
*/
---==================================创建表脚本=====================================
declare
iCnt number := 0;
begin
select count(*) into iCnt from user_tables where lower(table_name) = 't_user_info'; --根据表进行查询
if iCnt = 0 then -- 如果查询不到这个表就创建这个表
execute immediate 'create table t_user_info
(
user_id number not null,
user_name varchar2(32) not null,
pass_word varchar2(32) not null,
age number(10) not null,
create_time date,
id_card_code varchar2(38) not null
)';
execute immediate 'alter table t_user_info add constraint pk_user_id primary key (user_id)'; --主键
execute immediate 'create unique index idx_id_card_code on t_user_info (id_card_code)'; --对身份证号创建唯一索引
execute immediate 'comment on table t_user_info is ''用户表'''; --用户表描述
execute immediate 'comment on column t_user_info.user_id is ''主键(我方主键)'''; -- 主键描述
execute immediate 'comment on column t_user_info.user_name is ''用户名'''; -- 用户名描述
execute immediate 'comment on column t_user_info.pass_word is ''用户密码'''; -- 用户密码描述
execute immediate 'comment on column t_user_info.age is ''年龄'''; -- 年龄描述
execute immediate 'comment on column t_user_info.create_time is ''创建时间'''; -- 创建时间描述
execute immediate 'comment on column t_user_info.id_card_code is ''身份证号'''; -- 身份证号描述
end if;
end;
/
---==================================删除表***=====================================
declare
iCount integer; --声明一个整型的变量
begin
select count(*) into iCount from user_sequences where upper(sequence_name) = upper('SEQ_T_USER_INFO'); --upper表示转换为大写进行查询
if(iCount = 1 or iCount > 0 ) then --查到等于1或者是大于0就把这个***执行删除SQL语句
execute immediate 'drop sequence SEQ_T_USER_INFO';
end if;
end;
/
---==================================创建***脚本,每一个***对一个表=====================================
declare
iCnt integer;
begin
select count(*) into iCnt from user_sequences where upper(sequence_name)=upper('SEQ_T_USER_INFO');
if iCnt = 0 then
/*minvalue最小值为1
*maxvalue最大值为999999999999999999999999999
*start从1开始
*increment每插入一条递增1
*nocache无缓存
*/
execute immediate 'create sequence SEQ_T_USER_INFO
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
nocache';
end if;
end;
/
---==================================插入数据脚本=====================================
declare
iCnt number := 0;
SEQ_USER_ID number :=0;--序列id
begin
select count(*) into iCnt from user_tables where lower(table_name) = 't_user_info'; --根据表进行查询
select SEQ_T_USER_INFO.nextval into SEQ_USER_ID from dual;--获取主键序列
if iCnt = 1 then
insert into t_user_info (user_id, user_name, pass_word,age,create_time,id_card_code)
values (SEQ_USER_ID, '张三丰', '123456',100,sysdate,'X'||SEQ_USER_ID);
--或者直接序列.nextval values (SEQ_T_USER_INFO.nextval, '张三丰', '123456',100,sysdate,'X'||SEQ_USER_ID);
commit;--提交
end if;
end;
/
---==================================修改表脚本(递增字段脚本)=====================================
/*
alter table table_name
add
(
column1_name column1_datatype column1_constraint, ---列名,列名类型,列约束
column2_name column2_datatype column2_constraint,
............................
);
如:
alter table table_name
add
(
address char(1) NOT NULL,
sex number,
............................
);
*/
declare
iCnt number := 0;
begin
--对表添加字段,不对表select count(*)检测,原因:在升级脚本时,SQL脚本一般有主副脚本顺序规则执行,且最后脚本结尾加一个commit关键字,
--在主副脚本只仅有一个commit,故在升级sql脚本步骤先必须遵循升级前先主后副脚本(数据初始化,修改表结构,添加表结构等SQL脚本)执行
select count(*) into iCnt from user_tab_columns where lower(table_name) = 't_user_info' and lower(column_name) = 'update_time';
--查询不到这个update_time字段,然后往下面执行
if iCnt = 0 then
execute immediate 'alter table t_user_info add update_time date '; --对t_user_info表添加字段
execute immediate 'comment on column t_user_info.update_time is ''更新时间'''; -- 更新时间描述
end if;
end;
/
/* =================================存储过程 =================================*/
declare
iCnt integer; --声明变量
begin
--根据存储过程的名称进行查询是否存在存储过程.
SELECT count(*) into iCnt FROM USER_SOURCE WHERE TYPE = upper('procedure') and name in(upper('pro_user_info'));
if(iCnt = 1 or iCnt > 0 ) then
execute immediate 'drop procedure pro_user_info';
end if ;
end;
/
---创建存储过程
create or replace procedure pro_user_info(
vc_in_userName in varchar2, --用户名,输入参数
out_result out sys_refcursor -- 结果标识
) is
vc_sql varchar2(10000) := ''; --动态sql
begin
vc_sql := 'select user_id,user_name,age,create_time from t_user_info ';
--判断不为空的时候
if(vc_in_userName <> '') then
vc_sql := 'where user_name=:vc_in_userName';
execute immediate vc_sql using vc_in_userName;--执行
--open out_result for --打开游标
-- return; --返回游标值.
end if;
exception when others then rollback;
dbms_output.put_line('事务回滚');
end ;
Oracle笔记 http://jilongliang.iteye.com/blog/1850958
3.1创建表与插数据脚本
3.2添加或修改表脚本
3.3删除表脚本
3.4删除与创建索引脚本
3.5删除与创建序列脚本
3.6删除与创建存储过程脚本
3.7删除与创建视图脚本
四、开发环境与工具
4.1Nexu*仓库
Nexus 是Maven仓库管理器,如果你使用Maven,你可以从Maven*仓库 下载所需要的构件(artifact),但这通常不是一个好的做法,你应该在本地架设一
个Maven仓库服务器,在代理远程仓库的同时维护本地仓库,以节省带宽和时间,Nexus就可以满足这样的需要。此外,他还提供了强大的仓库管理功能,构件搜
索功能,它基于REST,友好的UI是一个extjs的REST客户端,它占用较少的内存,基于简单文件系统而非数据库。这些优点使其日趋成为最流行的Maven仓库管理器。
官方网:http://www.sonatype.org/nexus/
学习博客:http://blog.csdn.net/wang379275614/article/details/43940259
4.2 Eclipse
Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了
一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。
官方网:http://www.eclipse.org/downloads/
4.3 Tomcat
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun
的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet2.4和JSP2.0规范。因为Tomcat 技术先进、性能稳定,而且免费,因而
深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Tomcat服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的
首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat
部分是Apache服务器的扩展,但它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。诀窍是,当配置正确时,Apache 为HTML页
面服务,而Tomcat 实际上运行JSP页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器
是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。目前Tomcat最新版本为9.0
官方网:http://tomcat.apache.org/
4.4 JDK
JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境,JAVA工具和JAVA基础的类库
官方网:http://www.oracle.com/technetwork/java/javase/downloads/index.html
4.5Maven
Apache Maven是一个软件项目管理和理解工具。 基于项目对象模型(POM)的概念,Maven可以从*信息管理项目的构建,报告和文档。
官方网:http://maven.apache.org/
学习博客:
https://yq.aliyun.com/articles/28591
http://www.yiibai.com/maven/maven_project_documents.html
4.6ER-Ermaster
ERMaster是一个用于设计ER模型图的Eclipse插件。提供的功能包括:从数据库导入关系生成ER图,导出设计图,导出DDL数据定义语句等,详细教程请看
官方网:http://ermaster.sourceforge.net/
五、使用技术体系实现
5.1前端UI
5.1.1 BootStrap
BootStrap,来自 Twitter,是目前很受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷。
它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS
语言Less写成。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使
用了该项目。国内一些移动开发者较为熟悉的框架,如WeX5前端开源框架等,也是基于Bootstrap源码进行性能优化而来。
官方网: http://www.bootcss.com/
BootStrap图标:http://v3.bootcss.com/components/
5.1.2 Font Awesome
Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小、颜色、阴影或者其它任何支持的效果。
官方网:http://fontawesome.dashgame.com/
5.1.3 jQuery
jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)jQuery设计的宗旨是“write Less,Do More”,
即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制
和丰富的插件。jQuery兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等
官方网: http://jquery.com/
5.1.4 jQuery高亮插件
一款优秀的JavaScript代码高亮插件,将会帮助你渲染任何一种编程语言,包括一些关键字的着色,以及每行代码的缩进等,非常有效地帮你实现在网页上的代码编辑和展示。
在项目中我首选了SyntaxHighlighter
1、SyntaxHighlighter–最优秀的JavaScript代码高亮插件SyntaxHighlighter 是一款完全基于JavaScript的代码高亮插件,SyntaxHighlighter可以对大部分编程语言进行着色渲染,
而且代码高亮的性能也非常不错。SyntaxHighlighter 可以自定义主题文件,在初始化的时候指定自己喜欢的主题即可。
官方网站:http://alexgorbatchev.com/SyntaxHighlighter/
2、Google Code Prettify–*地JavaScript代码高亮插件Google Code Prettify是一款由Google推出的JavaScript代码高亮插件,Google Code Prettify可以对C/C++,Java
,Python,Ruby,PHP,VisualBasic,AWK,Bash,SQL,HTML,XML,CSS,JavaScript,Makefiles和部分Perl编程语言代码高亮着色。
官方网站:http://code.google.com/p/google-code-prettify/ 下载
3、Highlight.js –多风格JavaScript代码高亮插件Highlight.js是一个用于在任何web页面上高亮着色显示各种示例源代码语法的JavaScript项目。
官方网站:https://highlightjs.org/
4. Prism.JS - 轻量级JavaScript代码高亮插件Prism.JS是目前最为轻量级的JavaScript代码高亮插件,他压缩后只有2KB的大小,Prism.JS也支持大部分流行的编程语言,并且支
持多种主题样式,开发者只需要引用CSS文件和JS文件即可完成。
官方网站:http://prismjs.com/
5、jQuery.Syntax–jQuery轻量级代码高亮插件
这款代码高亮插件是基于jQuery的,同样也是轻量级的,渲染速度非常快。同时jQuery.Syntax还具有wordpress的插件应用,对于个人博主来说,使用wordpress和jQuery.Synt
ax可以完美实现0代买的高亮功能。
官方网站:http://www.codeotaku.com/projects/jquery-syntax/index.en
6、DlHighlight–jQuery简单高效代码高亮插件
DlHighlight是基于JavaScript的代码高亮插件,非常简单,目前只支持JavaScript, CSS, XML, HTML。
官方网站:http://mihai.bazon.net/projects/javascript-syntax-highlighting-engine
7、Rainbow.js – 可扩展的JavaScript代码高亮插件
Rainbow 是JavaScript开发的语法高亮工具。被设计为轻量级(压缩后仅1.4 kb),使用简单,可扩展。语法高亮主题完全通过CSS定义。基于正则表达式实现。
官方网站:http://craig.is/making/rainbows
5.2.5 LayerUI与jBox弹窗技术
layer是一款web弹层组件,致力于服务各个水平段的开发人员。
官方网: http://layer.layui.com/
http://www.5imvc.com/scripts/jbox/jbox-demo.html
官方API: http://layer.layui.com/api.html
5.2.6 colResizable拖拽插件
colResizable是一个jQuery插件,用于调整手动拖动HML的Table标签列。 它兼容鼠标和触摸设备,并具有一些不错的功能,如页面刷新或回发后的布局持久性。
这个插件在处理大表提高可用性时非常方便。 它的体积很小(colResizable 1.0只有2kb),它与所有主流浏览器(IE7 +,Firefox,Chrome和Opera)完全兼容。
官方网:http://www.bacubacu.com/colresizable/
5.2.7 bumpyText插件
bumpyText一款能让文字跳舞的jQuery文字插件,鼠标划过文字即可看到效果。兼容主流浏览器!
Github: https://github.com/alexanderdickson/bumpyText
5.2框架与技术
5.2.1 Servlet3.x
Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布。该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的
开发和部署。其中有几项特性的引入让开发者感到非常兴奋,同时也获得了 Java 社区的一片赞誉之声
推荐学习博客
https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/
http://jinnianshilongnian.iteye.com/category/255452
5.2.2 SpringMVC
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring
可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1,Struts2等。而且Spring
体系非常庞大,这里不做详细描述,想继续了解和学习请到官方网。
Spring官方网 http://spring.io
推荐学习博客:http://jinnianshilongnian.iteye.com/category/231099
5.2.3 ORM
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的
数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上
发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。对象关系映射(
Object-Relational Mapping)提供了概念性的、易于理解的模型化数
据的方法。
ORM方法论基于三个核心原则:
简单:以最基本的形式建模数据。传达性:数据库结构被任何人都能理解的语言文档化。精确性:基于数据模型创建正确标准化的结构。
典型地,建模者通过收集来自那些熟悉应用程序但不熟练的数据建模者的人的信息开发信息模型。建模者必须能够用非技术企业专家可以理解的术语在概念层次
上与数据结构进行通讯。建模者也必须能以简单的单元分析信息,对样本数据进行处理。ORM专门被设计为改进这种联系。比如:(JDBC,JdbcTemplate,Hibernate ,Ibatis/MyBatis)等
本项目框架在3年前工作中用到JdbcTemplate在资料的时候看到oschina大牛的一篇文章,故下决心通过学习整理一个SpringMVC工程作为技术积累。
推荐博客:https://www.oschina.net/code/snippet_1245103_33821
5.2.4 POI与JXL
简述:POI与JXL都是一个处理Excel文档的技术。个人认为:从两者的使用过程中的角度来看,JXL相对POI会轻巧,占空间内存少,Jar只有一个,上手快。
不过从知识上的支持没POI友好,实现方式没POI强大。毕竟POI是Apache下的工程项目。建议可以根据自己的情况进行选择与学习。
1、POI官方网: http://poi.apache.org/
2、JXL官方网: http://jxl.sourceforge.net/
3、入门例子:
https://github.com/jilongliang/excel-doc-pdf
https://github.com/jilongliang/JL_OutExcel
5.2.5 JSON
fastjson gson jackjson json-lib org.json
JSON工程例子代码 https://github.com/jilongliang/json
博客文章:http://blog.csdn.net/jilongliang/article/category/2813267
六、代码实现与效果
6.1Servlet3.x+jdbc实现
6.1.1Pojo
6.1.2Service
6.1.3Util
6.1.4Controler
6.1.5其他说明
1、Servlet3.x注意事项1
2、Servlet3.x注意事项2
由于jdbc实现代码较多和关闭数据源处理不好经常断,后面所有功能转为spring架构实现
6.1.6效果
启动Tomcat访问url:
http://localhost:8080/flong/sqlScriptController?executeMethod=queryTableList
6.2SpringMVC+JdbcTemplate实现
6.2.1Pojo
6.2.2Service
package com.flong.modules.service.impl;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.flong.commons.persistence.bean.SimplePage;
import com.flong.commons.persistence.dao.impl.EntityDaoSupport;
import com.flong.commons.utils.ObjectUtil;
import com.flong.modules.dao.TableColumnsDao;
import com.flong.modules.dao.TableDao;
import com.flong.modules.dao.UserColCommentsDao;
import com.flong.modules.dao.UserConsColumnsDao;
import com.flong.modules.dao.UserTabCommentsDao;
import com.flong.modules.pojo.Sequences;
import com.flong.modules.pojo.UserColComments;
import com.flong.modules.pojo.UserConsColumns;
import com.flong.modules.pojo.UserTabColumns;
import com.flong.modules.pojo.UserTabComments;
import com.flong.modules.pojo.UserTables;
import com.flong.modules.service.TableService;
/**
* @Description TODO
* @ClassName TableService
* @Date 2017年3月1日 上午10:48:44
* @Author liangjilong
* @Copyright (c) All Right Reserved , 2017.
*/
@Service
@Transactional
@SuppressWarnings("all")
public class TableServiceImpl extends EntityDaoSupport<UserTables> implements TableService {
@Autowired TableDao tableDao;
@Autowired TableColumnsDao tableColumnsDao;
@Autowired UserColCommentsDao userColCommentsDao;
@Autowired UserTabCommentsDao userTabCommentsDao;
@Autowired UserConsColumnsDao userConsColumnsDao;
public List<UserTables> queryTables(SimplePage page, UserTables object) {
return tableDao.queryTables(page,object);
}
public List<UserTables> queryTableByName(String table_name){
return tableDao.queryTableByName(table_name);
}
@Override
public String createTableSQLScript(String tableName) {
String result = "";
//1、判断是否存在这个表
List<UserTables> findList = queryTableByName( tableName);
//2、组装execute immediate 'create table ...'
if(findList!=null &&findList.size()>0){
StringBuffer buffer = new StringBuffer();
//3、获取表的字段名称,并且获取约束是否为空(Null or Not null)
List<UserTabColumns> userTabColumnList = tableColumnsDao.getUserTabColumnsByName(tableName);
List<UserTabComments> userTabCommentList = userTabCommentsDao.getUserTabCommentsByName(tableName);
List<UserColComments> userColCommentList = userColCommentsDao.getUserColCommentsByName(tableName);
UserConsColumns userConsColumns = userConsColumnsDao.getUserConsColumnsByName(tableName);
//----组装表字段列名
int size = userTabColumnList.size()-1;//计算最后一个表列名
buffer.append("--创建"+tableName+"表").append(ENTER);
buffer.append("declare").append(ENTER);
buffer.append(TAB).append("iCnt number := 0;").append(ENTER);
buffer.append("begin ").append(ENTER);
buffer.append(" select count(*) into iCnt from user_tables where lower(table_name) = lower('"+tableName+"');").append(ENTER);
buffer.append(" if iCnt = 0 then ").append(ENTER);
buffer.append(TAB).append("execute immediate 'create table "+tableName+"").append(ENTER);
buffer.append(TAB).append("(").append(ENTER);
for (int i = 0; i < userTabColumnList.size(); i++) {
UserTabColumns userTabColumns = userTabColumnList.get(i);
UserColComments userColComments = userColCommentList.get(i);
String column_name1 = userColComments.getColumn_name();//列名
String column_name2 = userTabColumns.getColumn_name();//列名
String nullable = userTabColumns.getNullable();//是否允许为空
String data_type = userTabColumns.getData_type();//数据库表的字段类型.
BigDecimal data_length = userTabColumns.getData_length();
BigDecimal data_precision = userTabColumns.getData_precision();
BigDecimal data_scale = userTabColumns.getData_scale();
if(ObjectUtil.isNotEmpty(column_name1) && ObjectUtil.isNotEmpty(column_name2) && column_name1.equalsIgnoreCase(column_name2)){
//判断表字段类型是否为NULL或NOT NULL
if(ObjectUtil.isNotEmpty(nullable) && !"N".equalsIgnoreCase(nullable)){
if(size==i){
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+")" ).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") ").append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) ").append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}
}else{
//为空但是有逗号分开
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+")" ).append(COMMA).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") ").append(COMMA).append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) ").append(COMMA).append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}
}
}else{
if(size==i){
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+") not null " ).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") not null").append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) not null ").append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type+"").append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}
}else{
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+") not null " ).append(COMMA).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") not null").append(COMMA).append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) not null ").append(COMMA).append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type+" ").append(COMMA).append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}
}
}
}
}
buffer.append(TAB).append(")';").append(ENTER);
//4、获取表名给予表加备注.(有就加,无默认表描述)
if(ObjectUtil.isNotEmpty(userTabCommentList) && ObjectUtil.isNotEmpty(userTabCommentList.get(0))){
String comments = userTabCommentList.get(0).getComments();
comments = (comments==null?" this is "+tableName+" tableName ":comments);
buffer.append(TAB).append("execute immediate 'comment on table "+tableName +" is ''"+comments+"'''").append(";").append(ENTER);
}
//5、添加主键执行SQL脚本
if(ObjectUtil.isNotEmpty(userConsColumns) && ObjectUtil.isNotEmpty(userConsColumns.getConstraint_name())){
buffer.append(TAB).append("execute immediate 'alter table "+tableName).append(" add constraint "+userConsColumns.getConstraint_name()+" ");
buffer.append("primary key ("+userConsColumns.getColumn_name()+")' ;").append(ENTER);
}
//6、获取表字段名给予字段加备注(有就加,无默认字段描述)
for(UserColComments col: userColCommentList){
String comments = col.getComments();
String column_name = col.getColumn_name();
comments = (comments==null?" this is "+column_name+" columnName ":comments);
buffer.append(TAB).append("execute immediate 'comment on column "+tableName+"."+col.getColumn_name()+" is ''"+comments+"'''").append(";").append(ENTER);
}
//---end if
buffer.append(" end if;").append(ENTER);
buffer.append("end;").append(ENTER);
buffer.append("/").append(ENTER);
result = buffer.toString();
}
return result;
}
@Override
public String dropTableSQLScript(String table_name) {
List<UserTables> list = queryTableByName(table_name);
StringBuffer buffer = new StringBuffer();
if(list!=null && list.size()>0){
UserTables sequences = list.get(0);
buffer.append("--"+table_name).append(ENTER);
buffer.append("declare").append(ENTER);
buffer.append(TAB+TAB).append("iCnt number := 0;").append(ENTER);
buffer.append(TAB).append("begin").append(ENTER);
buffer.append(TAB).append(" select count(*) into iCnt from user_tables where lower(table_name) = '"+table_name+"'; --根据表进行查询").append(ENTER);
buffer.append(TAB).append(" if iCnt > 0 then ").append(ENTER);
buffer.append(TAB).append(" execute immediate 'drop table "+table_name+"'; --删除表,表结构和数据一起清空 ").append(ENTER);
buffer.append(TAB).append(" end if;").append(ENTER);
buffer.append(TAB).append("end;").append(ENTER);
buffer.append("/").append(ENTER);
return buffer.toString();
}
return null;
}
}
6.2.3DAO
6.2.4Controler
package com.flong.modules.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import com.alibaba.fastjson.JSONObject;
import com.flong.codegenerator.FileUtils;
import com.flong.commons.persistence.bean.SimplePage;
import com.flong.commons.web.BaseController;
import com.flong.modules.pojo.UserTables;
import com.flong.modules.service.TableService;
/**
* @author liangjilong
*
*/
@Controller
@RequestMapping("table")
public class TableController extends BaseController{
@Autowired TableService tableService;
/***
* 查询所有Oracle内置数据库表或者视图信息
* @param tableIdentifiers
* @param page
* @param request
* @param response
* @return
*/
@RequestMapping(value="list")
public String list(UserTables userTables,SimplePage page ,HttpServletRequest request ){
List<UserTables> findList = tableService.queryTables(page, userTables);
request.setAttribute("userTables", userTables);
request.setAttribute("page", page);
request.setAttribute("list", findList);
return "modules/tableList";
}
/**
* @Description 根据表名进行查询表信息
* @Author liangjilong
* @Date 2017年3月27日 上午8:23:14
* @param table_name
* @param request
* @return 参数
* @return String 返回类型
*/
@RequestMapping(value="createTableSQLScript/{table_name}")
public String createTableSQLScript(@PathVariable String table_name,HttpServletRequest request ){
String resultSQLStr = tableService.createTableSQLScript(table_name);
request.setAttribute("resultSQLStr", resultSQLStr);
return "modules/sqlScriptInfo";
}
/**
* @Description 根据表名进行查询表信息
* @Author liangjilong
* @Date 2017年3月27日 上午8:23:14
* @param table_name
* @param request
* @return 参数
* @return String 返回类型
*/
@RequestMapping(value="dropTableSQLScript/{table_name}")
public String dropTableSQLScript(@PathVariable String table_name,HttpServletRequest request ){
String resultSQLStr = tableService.dropTableSQLScript(table_name);
request.setAttribute("resultSQLStr", resultSQLStr);
return "modules/sqlScriptInfo";
}
/**
*
* @Description 导出SQL
* 本来html的textarea标签可以使用js实现拷贝的,为了模仿iteye或者csdn博客开发页面拷贝功能的,由于找了好几个插件都没试出来,
* 而且他们都是使用swf插件实现,在脚本高亮在显示关键字就研究了SyntaxHighlighter导致textarea使用js拷贝功能失效就放弃按钮拷
* 贝功能。为了更加方便通过文件流处理,指定电脑硬盘路径和名称,并以.sql后缀文件直接输出,这样更方便帮助我们直接省了Ctrl+C
* 和Ctrl+V内容, //再新建文件整理脚本工作动作。cnblogs博客是双击代码,按 Ctrl+C复制代码(此时是jQuery高亮插件自带功能提示)
* 参考博客:http://www.cnblogs.com/tylerdonet/p/4533782.html
* @Author liangjilong
* @Date 2017年3月27日 上午8:21:15
* @param table_name
* @param request
* 参数
* @return void 返回类型
*/
@RequestMapping(value="exportCreateSQL/{table_name}")
public void exportCreateSQL(@PathVariable String table_name,HttpServletResponse response ){
String resultSQLStr = tableService.createTableSQLScript(table_name);
//这里为了快速方便使用指定路径实现,并以.sql后缀文件导出到指定硬盘。可以根据自己的情况进行修改,比如:你可以使用SpringMVC下载文件方式实现,
String path = "C://output-sql/"+"TableSQL-"+formatDate+".sql";
FileUtils.save(path, resultSQLStr);//保存文件
JSONObject jsonObject = new JSONObject();//使用fastjson技术实现ajax异步处理
jsonObject.put("path", path);
jsonObject.put("result", "1");
this.writeJson(jsonObject, response);
}
/**
*
* @Description 导出SQL
* 本来html的textarea标签可以使用js实现拷贝的,为了模仿iteye或者csdn博客开发页面拷贝功能的,由于找了好几个插件都没试出来,
* 而且他们都是使用swf插件实现,在脚本高亮在显示关键字就研究了SyntaxHighlighter导致textarea使用js拷贝功能失效就放弃按钮拷
* 贝功能。为了更加方便通过文件流处理,指定电脑硬盘路径和名称,并以.sql后缀文件直接输出,这样更方便帮助我们直接省了Ctrl+C
* 和Ctrl+V内容, //再新建文件整理脚本工作动作。cnblogs博客是双击代码,按 Ctrl+C复制代码(此时是jQuery高亮插件自带功能提示)
* 参考博客:http://www.cnblogs.com/tylerdonet/p/4533782.html
* @Author liangjilong
* @Date 2017年3月27日 上午8:21:15
* @param table_name
* @param request
* 参数
* @return void 返回类型
*/
@RequestMapping(value="exportDropSQL/{table_name}")
public void exportDropSQL(@PathVariable String table_name,HttpServletResponse response ){
String resultSQLStr = tableService.dropTableSQLScript(table_name);
//这里为了快速方便使用指定路径实现,并以.sql后缀文件导出到指定硬盘。可以根据自己的情况进行修改,比如:你可以使用SpringMVC下载文件方式实现,
String path = "C://output-sql/"+"TableSQL-"+formatDate+".sql";
FileUtils.save(path, resultSQLStr);//保存文件
JSONObject jsonObject = new JSONObject();//使用fastjson技术实现ajax异步处理
jsonObject.put("path", path);
jsonObject.put("result", "1");
this.writeJson(jsonObject, response);
}
}
6.2.5前端技术
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <style> a{cursor: pointer;} </style> <input type="hidden" id="pageNum" name="pageNum" value="${page.pageNum }"/> <input type="hidden" id="pageCount" name="pageCount" value="${page.pageCount }"/> <c:set var="startPage" value="${page.pageNum-page.pageNum%5+1 }"/> <c:if test="${page.pageNum%5==0 }"> <c:set var="startPage" value="${startPage-5 }"/> </c:if> <c:set var="endPage" value="${startPage+4 }"/> <c:if test="${page.pageCount-startPage < 5 }"> <c:set var="endPage" value="${page.pageCount }"/> </c:if> <nav> <ul class="pagination pagination-sm"> <li id="prvPage" onclick="goPage(1,this.id)"><a title="首页">«</a></li> <li id="last" class="<c:if test="${page.pageNum == 1 }">disable</c:if>" onclick="lastPage(this.id)"><a>上一页</a></li> <c:choose> <c:when test="${page.pageCount > 5 }"> <c:forEach var="startIndex" begin="${startPage }" end="${endPage }" step="1"> <li id="current" <c:if test="${page.pageNum == startIndex }">class="active"</c:if> onclick="goPage(${startIndex },this.id)"> <a>${startIndex }</a> </li> </c:forEach> </c:when> <c:otherwise> <c:forEach var="i" begin="1" end="${page.pageCount }" step="1"> <li id="current" <c:if test="${page.pageNum == i }">class="active"</c:if> onclick="goPage(${i },this.id)"> <a>${i }</a></li> </c:forEach> </c:otherwise> </c:choose> <li><a>...</a></li> <li><a>共${page.pageCount }页</a></li> <li id="next" class="<c:if test="${page.pageNum == page.pageCount }">disable</c:if>" onclick="nextPage(this.id)"><a>下一页</a></li> <li id="lastPage" onclick="goPage(${page.pageCount},this.id)"><a title="尾页">»</a></li> <span>到</span> <li> <input type="text" class="input-medium required digits" id="targetPage" style="width: 38px;height:30px; text-align: center;" value="${page.pageNum }" onkeyup="this.value=this.value.replace(/\D/g,'')" onblur="checkPageNum(this)"> </li> <span>页 共<strong>${page.rowCount}</strong>条</span> <input id="go" type="button" value="确定" class="sure btn btn-sm btn-success" onclick="goPage($('#targetPage').val(),this.id)"> </ul> </nav> <script type="text/javascript"> /** *此分页必须要有表单有有一个Id,而且class=form-search.form表单必须包括分页common-pagination.jsp */ /**执行第一页**/ function setStart(){ $('#pageNum').val(1); } /**检查这个页数**/ function checkPageNum(obj){ var pageCount = $('#pageCount').val(); if(obj.value > parseInt(pageCount)){ //如果大于当前页数的时候就变成btn白色. $('#go').attr('class', 'sure btn-sm disable'); }else{ $('#go').attr('class', 'btn btn-sm'); } } /**执行分页**/ function goPage(pageNum,obj){ var formId = $('#' + obj).parents(".form-search").attr('id'); var pageCount = $('#pageCount').val(); if(parseInt(pageNum) <= parseInt(pageCount)){ $('#pageNum').val(pageNum); $('#' + formId).submit(); } } /**执行最后一页**/ function lastPage(obj){ var formId = $('#' + obj).parents(".form-search").attr('id'); var pageNum = $('#pageNum').val(); var lastPageNum = parseInt(pageNum) - 1; if(lastPageNum != 0){ $('#pageNum').val(lastPageNum); $('#' + formId).submit(); } } /**执行下一页**/ function nextPage(obj){ var formId = $('#' + obj).parents(".form-search").attr('id'); var pageNum = $('#pageNum').val(); var pageCount = $('#pageCount').val(); var nextPageNum = parseInt(pageNum) + 1; if(parseInt(pageNum) < parseInt(pageCount)){ $('#pageNum').val(nextPageNum); $('#' + formId).submit(); } } </script>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="/WEB-INF/views/include/taglib.jsp"%> <!DOCTYPE htm> <html> <head> <%@ include file="/WEB-INF/views/include/meta.jsp"%> <%@ include file="/WEB-INF/views/include/include.jsp"%> <title></title> <style> .breadcrumb{ background-color: #fff; } .form-search{ background-color: #fff; } .form-search1{ padding: 8px 15px; background-color: #f5f5f5; } </style> </head> <body> <ul class="nav nav-tabs"> <li><a href="${basePath}tableIdentifiers/list">主键管理</a></li> <li class="active"><a href="${basePath}table/list">表管理</a></li> <li><a href="${basePath}view/list">视图管理</a></li> <li ><a href="${basePath}sequence/list">序列管理</a></li> <li ><a href="${basePath}index/list">索引管理</a></li> </ul> <form:form id="searchForm" modelAttribute="userTables" action="${basePath}table/list" method="post" class="breadcrumb form-search form-inline"> <div style="margin-bottom: 20px;" class="form-search1"> <label>TableName :</label><form:input path="table_name" htmlEscape="false" maxlength="50" class="input-medium form-control" placeholder="TableName"/> <input id="btnSubmit" class="btn btn-info" type="submit" value="查询"/> </div> <table id="contentTable" class="table table-striped table-bordered table-hover"> <thead> <tr> <th style="width: 58px;">编号</th> <th>表名称</th> <th>表空间名称</th> <th>操作</th> </tr> </thead> <tbody> <c:forEach items="${list}" var="obj" varStatus="row"> <tr> <td>${row.index+1}</td> <td>${obj.table_name}</td> <td>${obj.tablespace_name}</td> <td> <!-- 使用ont-awesome或者fbootstrap图标库 --> <i class="fa fa-binoculars"></i> <a href="${basePath}table/dropTableSQLScript/${obj.table_name}" onclick="return createSQL('生成删除表SQL脚本',this.href);">生成删除脚本</a> <i class="fa fa-binoculars"></i> <a href="${basePath}table/createTableSQLScript/${obj.table_name}" onclick="return createSQL('生成创建表SQL脚本',this.href);">生成创建脚本</a> <i class="glyphicon glyphicon-export"></i> <a href="${basePath}table/exportDropSQL/${obj.table_name}" onclick="return exportSQL('确定要导出删除表脚本?',this.href);">导出删除脚本</a> <i class="glyphicon glyphicon-export"></i> <a href="${basePath}table/exportCreateSQL/${obj.table_name}" onclick="return exportSQL('确定要导出创建表脚本?',this.href);">导出创建脚本</a> </td> </tr> </c:forEach> </tbody> </table> <%@ include file="/WEB-INF/views/include/pagination.jsp"%> </form:form> </body> </html>
6.2.6Java的JXL实现与Python的xlrd的实现
Excel模板
运行代码:
生成声明式高级SQL脚本
Python3.x 实现
# -*- coding:utf-8 -*- 处理乱码
import xlrd
#import xlwt
'''
@Author jilongliang
@Date 2017-04-12
@Copyright (c) All Right Reserved jilong, 2017.
@Description
xlwt和xlwt安装步骤,请参考博客 http://www.cnblogs.com/sincoolvip/p/5967010.html
http://www.cnblogs.com/lhj588/archive/2012/01/06/2314181.html
'''
#===============全局变量====================
TAB = " "; #空格置位常量
COMMA = ","; #SQL逗号常量
ENTER = "\n"; #换行常量
#===================================
#--------------定义一个读取excel的方法---------
def read_excel():
resultSQL = "";#返回SQL
#打开文件,Python中以r或R开头的的字符串表示(非转义的)原始字符串.说明字符串r"XXX"中的XXX是普通字符。
workbook = xlrd.open_workbook(r'D:\table_all.xls')
#获取所有sheet
sheet_names = workbook.sheet_names() # [u'sheet1', u'sheet2']
#遍历读取excel的每个sheet
#for sheet_name in sheet_names:
#print(sheet_name)
#遍历读取excel的每个sheet并且读取有多少个sheet的tab
for sheet_i in range(len(sheet_names)):
sheetName =sheet_names[sheet_i];#sheetName就是表名,在创建excel的时候规定好即可
sheet = workbook.sheet_by_index(sheet_i) #获取excel里面有哪些sheet
nrows = sheet.nrows #读取每个sheet有多少行(sheet里面一个table表格有多少行)
sqlStr = "--创建"+sheetName+"表SQL脚本"+ENTER;#表描述
sqlStr += "declare"+ENTER;#declare关键字
sqlStr += TAB+"iCnt number := 0; "+ENTER;#查询是否存在此表的记录数变量
sqlStr +="begin "+ENTER;#begin关键字
sqlStr +=TAB+"select count(*) into iCnt from user_tables where lower(table_name) = lower('"+sheetName+"'); "+ENTER;
sqlStr +=TAB+"if iCnt = 0 then -- 如果查询不到这个表就创建这个表"+ENTER;
sqlStr +=TAB+"execute immediate 'create table "+sheetName+" "+ENTER;#组装创建表SQL脚本
sqlStr +=TAB+"("+ENTER;
#遍历每个sheet里面的table有多少行
for row_i in range(nrows):
if row_i==2:
#cell(row_i,1)表示从shee的表格的第三行获取第二个列单元信息
fieldName = sheet.cell(row_i,1).value;#获取字段名称
fieldType = sheet.cell(row_i,2).value;#获取字段类型
fieldLength = sheet.cell(row_i, 3).value;#获取字段长度
isNull = sheet.cell(row_i, 4).value;#获取字段是否为空
if fieldLength!='':
fieldLength = '%s' %int(fieldLength) #把数字转换成String类型
else:
fieldLength = fieldLength
fieldLength = '%s' %fieldLength #把数字转换成String类型
fieldType = fieldType.upper();#转换成大写
#判断是否为Y/N
if isNull!='' and isNull== 'N':#判断字段为N
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
else: #判断字段为Y
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") " +COMMA + ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+")" +COMMA + ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")>-1 ):
sqlStr += TAB+TAB+fieldName+TAB+fieldType + COMMA + ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif row_i>2:
fieldName = sheet.cell(row_i,1).value;#获取字段名称
fieldType = sheet.cell(row_i,2).value;#获取字段类型
fieldLength = sheet.cell(row_i, 3).value;#获取字段长度
isNull = sheet.cell(row_i, 4).value;#获取字段是否为空
if fieldLength!='':
#从excel读取出来的数字是有小数点,先转换成整型,由于Python在拼接String的时候,int或double当数字相加了,故要转换成String进行拼接
#为了学习阶段目前这里使用spit分割出来,加强进一步学习,double和int是没有split方法
newFieldLength = '%s'%fieldLength;#double和int是没有split方法所以转换成一个string类型
if newFieldLength.find(".")>-1: #找到.之后进行处理获取第0个数字进行处理转换
fieldLengths = newFieldLength.split(".");#split进行分割
fieldLength = fieldLengths[0];#获取第0个数字
fieldLength = '%s' %int(fieldLength) #把数字转换成String类型
else:
fieldLength = fieldLength #处理为空的数字长度
fieldLength = '%s' %fieldLength #把数字转换成String类型
fieldType = fieldType.upper();#转换成大写
#判断是否为Y/N
if isNull!='' and isNull== 'N':#判断字段为N
#计算是否最后一个字段
if nrows-1 ==row_i :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
else :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
else : #判断字段为Y
#计算是否最后一个字段
if nrows-1 ==row_i :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
else :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+COMMA+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+COMMA+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
#---nrows for循环结束
sqlStr += TAB+")'; "+ENTER;#创建表脚本结束
comentSQL = addTableAndColumnComent(sheet, nrows); #对表与字段进行添加备注描述
sqlStr += comentSQL;
sqlStr += TAB+"end if; "+ENTER;#if脚本结束
sqlStr += "end; "+ENTER#sql脚本结束
sqlStr += "/"+ENTER;#sql脚本结束
#sqlStr=sqlStr.encode('utf8')
resultSQL += sqlStr; #累计SQL
#------sheet_names for循环结束
print(resultSQL);#打印结果
#--------------添加表名与列的注释方法---------
def addTableAndColumnComent(sheet,nrows):
resultSQL ="";
for row_i in range(nrows):
if(row_i==0):
tableName = sheet.cell(row_i,1).value;#获取表名称
tableNameDesc = sheet.cell(row_i,2).value;#获取表描述
if tableNameDesc=='' :
tableNameDesc = " this is "+tableName+" tableName "
else :
tableNameDesc = tableNameDesc
elif (row_i==2):
isPrimaryKey = sheet.cell(row_i,0).value;#获取表主键
tableName = sheet.cell(0,1).value;#获取表名称
fieldName = sheet.cell(row_i,1).value;#获取字段
if isPrimaryKey!='' :
resultSQL += TAB+"execute immediate 'alter table "+tableName+" add constraint PK_"+fieldName+" ";
resultSQL += " primary key ("+fieldName+")' ;"+ENTER;
elif(row_i>2):
tableName = sheet.cell(0,1).value;#获取表名称
fieldName = sheet.cell(row_i,1).value;#获取字段
fieldDescription = sheet.cell(row_i,6).value;#获取字段描述
if fieldName!='':
resultSQL += TAB+"execute immediate 'comment on column "+tableName+"."+fieldName+" is ''"+fieldDescription+"'''"+";"+ENTER;
#----for end
return resultSQL;
#在很多python脚本中在最后的部分会执行一个判断语句if __name__ == "__main__:",之后还可能会有一些执行语句。那添加这个判断的目的何在?
#在python编译器读取源文件的时候会执行它找到的所有代码,而在执行之前会根据当前运行的模块是否为主程序而定义变量__name__的值为__main__还是模块名。
#因此,该判断语句为真的时候,说明当前运行的脚本为主程序,而非主程序所引用的一个模块。这在当你想要运行一些只有在将模块当做程序运行时而非当做模块引用时才执行
#的命令,只要将它们放到if __name__ == "__main__:"判断语句之后就可以了
if __name__ == '__main__':
read_excel()
在初学者学Python的时候,会经常遇到的问题,如下:tab置位不一致会编译不过,因为Python代码讲究美观,简洁等情况。截图描述一下
6.2.7Util底层封装代码
6.2.8其他说明
如果在运行项目的时候,报Spring监听的时候,说明没找到Maven,引用jar,
解决方法加上Maven 库或者运行maven istanll拷贝jar到工程lib下面【在pom.xml已经配置好】拷贝成功之后此时可以再运行web工程就无错误.
Web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>flong</display-name> <!-- 参数初始化类配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:spring/spring-context.xml, classpath*:spring/spring-timer.xml </param-value> </context-param> <context-param> <param-name>spring.profiles.default</param-name> <param-value>production</param-value> </context-param> <!-- ===================================encoding=========================================== --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- ===================================SpringMVC=========================================== --> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- ===================================error-page=========================================== --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/WEB-INF/views/error/500.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/WEB-INF/views/error/500.jsp</location> </error-page> <error-page> <error-code>400</error-code> <location>/WEB-INF/views/error/400.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/WEB-INF/views/error/403.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/WEB-INF/views/error/404.jsp</location> </error-page> </web-app>
6.2.9功能与效果
其中有表管理,视图管理,序列管理,索引管理,每个管理都有【删除与创建脚本功能,导出删除和导出创建脚本功能】
启动Tomcat访问url:http://localhost:8080/generator/table/list
1、整体功能--表管理
2、整体功能--视图管理
3、整体功能--序列管理
4、整体功能--索引管理
6、生成删除表SQL脚本
7、生成创建表SQL脚本
8、导出删除表SQL脚本
9、导出创建表SQL脚本
七、个人总结
7.1为什么要总结
1、常言道:一分耕耘一分收获。总结能肯定自己劳动成果,帮助自己找出优缺点。
2、在扬长避短的情况下不断完善自己不足,针对性的学习。
7.2为什么记录笔记
1、在平时工作下来,一天认真工作下来,脑子肯定非常很疲倦,故经常健忘。也许跟年龄的岁数增大有关系。人精力与体力等各方面都有限的,毕竟人不是机器。
2、常言道:好记性不如烂笔头。切记千万别以自己有点小聪明对自己懒惰。
3、如果经常健忘的时候,不防借助一些软件工具或者云服务进行帮助存储生活中的痕迹。比如:思维导图(XMind, MindManager,FreeMind)云道笔记等等方式。
7.3其他说明
1以上问题都是根据自己工作实际情况进行总结整理,除了技术问题查很多网上资料通过进行学习之后梳理。
2在学习过程中也遇到很多困难和疑点,如有问题或误点,望各位老司机多多指出或者提出
建议。本人会采纳各种好建议和正确方式不断完善现况,人在成长过程中的需要优质的养料。
3 导入代码的时候遇到最多的问题,我想应该是Maven较多,此时不懂maven的童鞋们可以通过自身情况,进行网上查资料学习。如通过网上找资料长时间解决不了,
或者框架有不明白可以通过博客留言或者aaa@qq.com邮箱进行提问,在能力范围内会尽力帮助大家解决问题所在,希望在过程中一起进步,一起成长。
请牢记一句话:内事问度娘, 外事问谷歌,仅供参考学习。
源代码下载地址 http://download.csdn.net/detail/l_ji_l/9797834
上一篇: 解析PHP数据类型之数组(Array)