hap项目功能总结,以及技术注意点

非常重要,一定要注意,在项目上一旦不判空出现了问题,属于事故
1.物料批 mt_material_lotmt_eo表,这两张表的查询,一定不能用全表查询,sql层面一定要走 条件查询,同样java层面一定要 传参过去,传参时,一定要 先判空先

2.hap建索引的命名规范
唯一索引:table_U1,2,3…(索引名都是大写)
普通索引:table_N1,2,3…
主键索引:table_PK

3.oracle的中的 串类型的处理 有三种
varchar
clob(hap用的多 文本) 对应java类型 String
blob(二进制 图片) 对应java类型 byte[]

注意:
1.直接查询的话 对 clob类型不用做任何处理,映射到java类型 就是 String
2.如果是要在 PL/SQL看效果,那么直接查询,字段框内只显示一个 clob(因为太长了,PL/SQL 默认不显示)
解决办法:
1.select to_char(clob) 这样在 字段框就可以看到 字符串了
2.在 PL/SQL 点击弹框 弹出 字符串的内容

4.包名用_隔开,大多以 核心表命名(前提是有核心表)

5.开发时,大多模块都涉及一张核心表,你就看 更新插入时,是操作哪张表,或者看文档功能总结,就知道了,其他都是关联表

6.少数业务,是没有核心表的,存开发api ,那就是见名知意,用_隔开

7.方法命名,查询用 get 查询一个对象:getUserById() ,查询集合:UserList()

8.文档中的 api名不要改

9.list,字符串 的拼接,截取也是很常见的,

10.对象转list 数组转list 都是用 Arrays.asList();

11.去重的几种方式

12.oracle建表规范,建表,建seq,不建触发器,插入 mt_sys_sequence表 seq字段和初始值

13.导入导出的自定义,以及在哪做导入字段的校验??
标准导入导出按钮标签(没有自定义)
导入

<span class="btn btn-primary k-grid-excel" style="float:left;" onclick='Hap.importExcel("")' >
	<i class="fa fa-arrow-circle-up" style="margin-right:3px;">
	i><@spring.message "excel.import"/>

导出

 <span class="btn btn-primary k-grid-excel" style="float:left;margin-right:5px;" data-bind="click:exportExcel"><i class="fa fa-file-excel-o" style="margin-right:3px;">i>导出span>

14.lov查询除了查id , code , 如果要带出name,还得查 name (lov不能查 date类型的,时间用 时间选择器组件input框)

15.注意,VO和resultmap一定要继承,不然数据没有值,你在也不知道

16.kendoUi前端使用的几个注意点

1.grid不可编辑:

 {
                field: "name",
                title: '姓名',
                width: 120,
                headerAttributes: {style: "text-align:center"},
                attributes: {style: "text-align:center"},
                editor: function(container,options){
                        container.html(options.model.name);
                        container.removeClass('k-edit-cell');
                }
            },

2.form不可编辑? 不会

3.必输校验 ?不会

4.选定lov 后带出 name框的值(就是将lov查出的 name 也赋值给 viewModel ,这样 lov框选中值后,name也赋上值了,判断的name框的值也就达到了自动带出的效果了)

 {
                field: "employeeId",
                title: '用户名',
                width: 120,
                headerAttributes: {style: "text-align:center"},
                attributes: {style: "text-align:center"},
                template: function (dataItem) {
                    return dataItem['employeeCode'] || ''; /* 数据列默认显示值 */
                },
                editor: function (container, options) {
                    $('<input required name="' + options.field + '" />').appendTo(container)
                        .kendoLov($.extend( <@lov"EMPLOYEE_LOV"/>, {

                        select: function (e) {
                            // 将选择后的属性更新到数据模型中以保存
                            options.model.set('employeeId', e.item.employeeId);
                            
                            //重要的就是这个,带出name值,就是给name赋值
                            options.model.set('name',e.item.name); 
                        },
                        //TODO 之前的toolCategoryCode
                        textField: 'employeeCode', /* 编辑器显示的值 */
                        model: options.model
                    }));
                }

5.下拉框默认值(optionLabel: “是”)

 editor: function (container, options) {
                    $('<input required name="' + options.field + '"/>')
                        .appendTo(container)
                        .kendoDropDownList({
                            dataTextField: "meaning",   //显示的文本
                            dataValueField: "value",    //实际的值
                            optionLabel: "是",//默认选项值
                            dataSource: YES_NO,
                            valuePrimitive: true
                        });
                }

16.唯一性校验,一般在后台校验,比较麻烦

17.描述维护,就是 消息维护,{0}代表第一个参数

18.前端页面只要有不会的,可以考虑 借鉴其他页面的源码来修改,而不是直接百度 kendoui ,或者 hap

19.表里面的 cid 用的多,代表时间戳或者序号,和 主键一样,要创建 sequence,插入的时候,insert(主键 , cid) vaules(seq_s.nextvalue , seq_cid_s.nextvalue)创建的代码已经创建好了的

20.grid 和 他的 viewModel是 跟 接口打交道的 根本,而不是前面 表单,前面的所****有div ,都得绑定好

 <script>kendo.bind($('#div 的 id'), viewModel);script>

这样保证,这些div 的script事件是,将 数据 绑定到 对应 grid的 viewModel
同样这些 div里面的 lov 下拉框,也要有对应的 script,这些script就是,首先调用对应的下拉框 或 lov 然后,将框里面的值,赋值给 viewModel 例如

<script>
            $("#siteId").kendoLov($.extend(${lovProvider.getLov(base.contextPath, base.locale,
                                    "LOV_SITE")}, {
                select: function (e) {
                    viewModel.model.set("siteId", e.item.siteId);
                }
            }));
        script>

21.

<script type="text/javascript">
    var viewModel = Hap.createGridViewModel("#grid");
	var viewModelLine = Hap.createGridViewModel("#gridLine")
script>

这个代表的是,grid里面的 viewModel也就是数据模型,这是 grid的根本,viewModel 不是说对应的 实体类的json或者 说 colums的json,他在创建的时候,就是一个 map 里面的 key value都是为null的,
var viewModel = Hap.createGridViewModel(“#grid”);
这句最先执行
然后在,访问接口之前,你可以给 viewModel赋值,后,最先访问 read接口,这时在parameterMap中,对viewModel初始化了一下

你可以随便put 键值对,但是,一般

 			parameterMap: function (options, type) {
                if (type !== "read" && options.models) {
                    var datas = Hap.prepareSubmitParameter(options, type)
                    return kendo.stringify(datas);
                } else if (type === "read") {
                    return Hap.prepareQueryParameter(viewModel.model.toJSON(), options)
                }
            }

这是 viewModel的初始化,代码,这话的意思其实很简单,就是 调用查询方法,将查询出来的 JSON 赋值给 viewModel,所以说,viewModel的初始 key 是和 查询出来的,json相对应的
至于,comlun字段 和 viewModel是有关系的,在不做特定改变的情况下(例如下拉框,lov等),默认 filed和 viewModel的 key相同的 就取 对应的 value值

总之,viewModel是 数据模型,是整个 grid取值的依据的命脉,也是 于接口打交道,给接口传参的命脉

一切的 值的保存 和 取值,都要考虑到 viewModel ,例如 条件查询框,在取值后,一定要记得 给 viewModel赋值,这样 在访问接口的时候,这个框里面的值,才能传过去。

22. $(“#grid”).kendoGrid({
dataSource: dataSource,
resizable: true,
scrollable: true,
navigatable: false,
selectable: ‘multiple, rowbox’,
autoBind: 代表 gird自动不自动加载
editable: false 代表 grid不可编辑
})

字段隐藏

 {
                field: "cid",
                hidden: true
            },

22:整个页面需要的关注点
1.各个div
2.grid
3.各个事件发生 绑定的 script ,各个div绑定的 script …(script)
4.viewModel
5.viewModel赋值,取值的几个位置,script里面,paramterMap viewMoel初始化的时候,头行,传值,赋值给 viewModel的时候

23.在 script里面是可以 定义 变量的

24.头行明细
1.第一步,定义 2个 grid的 viewModel

<script type="text/javascript">
    var viewModel = Hap.createGridViewModel("#grid");
	var viewModelLine = Hap.createGridViewModel("#gridLine")
script>

2.第二步,定义头的div 和 行的 div
头div

<div id="page-content">
    <div class="pull-left" id="toolbar-btn" style="padding-bottom:10px;">
        <span class="btn btn-primary k-grid-add" style="float:left;margin-right:5px;" data-bind="click:create"><@spring.message "hap.new"/>span>
        <span class="btn btn-success k-grid-save-changes" data-bind="click:save" style="float:left;margin-right:5px;"><@spring.message "hap.save"/>span>
        <span  data-bind="click:remove" class="btn btn-danger" style="float:left;"><@spring.message "hap.delete"/>span>
    div>
    <script>kendo.bind($('#toolbar-btn'), viewModel);script>

    <div class="pull-right" id="query-form" style="padding-bottom:10px;">
        <input type="text" data-role="maskedtextbox" style="float:left;width:150px;margin-right:5px;" placeholder='<@spring.message "OdInspectionPlan.inspectionPlanCode"/>'
               data-bind="value:model.inspectionPlanCode" class="k-textbox">

        <input type="text" data-role="maskedtextbox" style="float:left;width:150px;margin-right:5px;" placeholder='<@spring.message "OdInspectionPlan.inspectionPlanName"/>'
               data-bind="value:model.inspectionPlanName" class="k-textbox">

        <input placeholder='<@spring.message "bom.sitecode"/>'
               data-bind="value:model.siteId" id="siteId">
        <script>
            $("#siteId").kendoLov($.extend(${lovProvider.getLov(base.contextPath, base.locale,
                                    "LOV_SITE")}, {
                select: function (e) {
                    viewModel.model.set("siteId", e.item.siteId);
                }
            }));
        script>

        <input placeholder='<@spring.message "odinspectionplan.materialid"/>'
               data-bind="value:model.materialId" id="materialId">
        <script>
            $("#materialId").kendoLov($.extend(${lovProvider.getLov(base.contextPath, base.locale,
                                    "LOV_MATERIAL")}, {
                select: function (e) {
                    viewModel.model.set("materialId", e.item.materialId);
                }
            }));
        script>

        <input placeholder='<@spring.message "odinspectionplan.status"/>'
               data-bind="value:model.status" id="status">
        <script>
            $("#status").kendoComboBox({
                dataTextField: "meaning",
                dataValueField: "value",
                valuePrimitive: true,
                dataSource: STATUS
            });
        script>

        <input placeholder='<@spring.message "odinspectionplan.identifycategory"/>'
               data-bind="value:model.identifyCategory" id="identifyCategory">
        <script>
            $("#identifyCategory").kendoComboBox({
                dataTextField: "meaning",
                dataValueField: "value",
                valuePrimitive: true,
                dataSource: I_CATE
            });
        script>

        <span class="btn btn-primary" style="float:left;width:70px" data-bind="click:query" type="submit"><@spring.message "hap.query"/>span>

    div>
    <script>kendo.bind($('#query-form'), viewModel);script>
	
	

    
    <div id = "xxx" style="clear:both">
        <div id="grid">div>
    div>
    <script>kendo.bind($('#xxx'), viewModel);script>
div>

行div


<div class="pull-left" id="toolbar-btn1" style="padding-bottom:10px;">
    <span class="btn btn-primary k-grid-add" style="float:left;margin-right:5px;" data-bind="click:create"><@spring.message "hap.new"/>span>
    <span class="btn btn-success k-grid-save-changes" data-bind="click:save" style="float:left;margin-right:5px;"><@spring.message "hap.save"/>span>
    <span  data-bind="click:remove" class="btn btn-danger" style="float:left;"><@spring.message "hap.delete"/>span>
div>
<script>kendo.bind($('#toolbar-btn1'), viewModelLine);script>

<div id="bottom-content" style="clear:both;margin: 10px 5px 5px;">
    <div id="gridLine">div>
div>
<script>kendo.bind($('#bottom-content'), viewModelLine);script>

3.定义头和行的 script grid
头的grid


<script type="text/javascript">
    <!--绑定前面的 html 内容  -->
    Hap.initEnterQuery('#query-form', viewModel.query);
    var BaseUrl = _basePath;
    dataSource = new kendo.data.DataSource({
        transport: {
            read: {
                url: BaseUrl + "/calb/od/inspection/plan/query",
                type: "POST",
                dataType: "json"
            },
            update: {
                url: BaseUrl + "/calb/od/inspection/plan/submit",
                type: "POST",
                contentType: "application/json"
            },
            destroy: {
                url: BaseUrl + "/calb/od/inspection/plan/remove",
                type: "POST",
                contentType: "application/json"
            },
            create: {
                url: BaseUrl + "/calb/od/inspection/plan/submit",
                type: "POST",
                contentType: "application/json"
            },

			//这里比较重要,这里是初始化 viewModel的代码,如果是查询的话,那么viewModel初始值和查询的VO的json串一样
            parameterMap: function (options, type) {
                if (type !== "read" && options.models) {
                    var datas = Hap.prepareSubmitParameter(options, type)
                    return kendo.stringify(datas);
                } else if (type === "read") {
                    return Hap.prepareQueryParameter(viewModel.model.toJSON(), options)
                }
            }
        },
        batch: true,
        serverPaging: true,
        pageSize: 10,
        schema: {
            data: 'rows',
            total: 'total',
            model: {
                id: "inspectionPlanId",
                fields: {}
            }
        }
    });

    $("#grid").kendoGrid({
        dataSource: dataSource,
        resizable: true,
        scrollable: true,
        navigatable: false,
        selectable: 'multiple, rowbox',
        dataBound: function () {
            if (parent.autoResizeIframe) {
                parent.autoResizeIframe('${RequestParameters.functionCode!}')
            }
        },
        pageable: {
            pageSizes: [5, 10, 20, 50],
            refresh: true,
            buttonCount: 5
        },
        columns: [
            {}
        ],
        editable: true
    });

script>

行的grid

<script>
    //判断数据是否为空  data 就是 点击的 那行的 grid的 viewModel的 一行的数据
    function ifNotNull(data) {
        if (data != null && data != "" && data != undefined) {
            return true;
        }
        return false;
    }

    var BaseUrl = _basePath;
    
    //头点击事件,这是头点击的核心代码,主要的作用就是,将data的 palnId赋值给 这个 viewModelLine
    myGrid2 = $("#grid").data("kendoGrid");
    $("#grid").on('click', 'td', function () {
        $("#head-div table tr").css("background-color", "#fff");
        var rowIndex = $(this).parent().index();
        $(this).parent().css("backgroundColor", "#acb4af");
        var data = myGrid2.dataSource.data()[rowIndex];
        if (!ifNotNull(data)) {
        } else {
            var inspectionPlanId = data.inspectionPlanId;
			
			//这两句本质没区别,两种写法
            viewModelLine.model.inspectionPlanId = inspectionPlanId;
            viewModelLine.model.set("inspectionPlanId",inspectionPlanId);
            
            $('#gridLine').data('kendoGrid').dataSource.page(1);
        }
    });
    dataSourceLine = new kendo.data.DataSource({
        transport: {
            read: {
                url: BaseUrl + "/calb/od/inspection/rel/query",
                type: "POST",
                dataType: "json"
            },
            update: {
                url: BaseUrl + "/calb/od/inspection/rel/submit",
                type: "POST",
                contentType: "application/json"
            },
            destroy: {
                url: BaseUrl + "/calb/od/inspection/rel/remove",
                type: "POST",
                contentType: "application/json"
            },
            create: {
                url: BaseUrl + "/calb/od/inspection/rel/submit",
                type: "POST",
                contentType: "application/json"
            },
             parameterMap: function (options, type) {
                if (type !== "read" && options.models) {
                    var datas = Hap.prepareSubmitParameter(options, type)
                    return kendo.stringify(datas);
                } else if (type === "read") {
                    return Hap.prepareQueryParameter(viewModelLine.model.toJSON(), options)
                }
            }
        },
        batch: true,
        serverPaging: true,
        pageSize: 10,
        schema: {
            data: 'rows',
            total: 'total',
            model: {
                id: "inspectionRelId",
                fields: {}
            }
        }
    });
    $("#gridLine").kendoGrid({
        dataSource: dataSourceLine,
        resizable: true,
        scrollable: true,
        autoBind: false,  //代表只有点击过后 才加载grid这句话一定要加上
        navigatable: false,
        selectable: 'multiple, rowbox',
        dataBound: function () {
            if (parent.autoResizeIframe) {
                parent.autoResizeIframe('${RequestParameters.functionCode!}')
            }
        },
        pageable: {
            pageSizes: [5, 10, 20, 50],
            refresh: true,
            buttonCount: 5
        },
        columns: [
            {}
        ],
        editable: true
    });
script>

头行最重要的两点就是
1.头点击事件代码中 给 viewModel赋值 头id
2.行的 gird中的 autoBind 一定要是 false 即 不自动加载 要点击后在加载

明细
1.首先在 行的gird中要加一个框,这个框不代表任何 field,只是用作显示,和 超链接点击 弹出 dilog框并传参数 (根据业务看要把 根据哪个字段 查 明细表),
注意

 {
                title: '<@spring.message "odinspectionrel.detail"/>',
                width: 120,
                attributes: {style: "text-align:center"},
                headerAttributes: {style: "text-align:center"},
                
                //重要代码,在这个框内显示"明细两字",点击将 参数 传到对应 diolog框的对应函数中去
                  dialog框的函数,去请求到某个地址去
                template: function (rowdata) {
                    return '<a style="text-decoration : underline; color :blue; cursor:pointer" onclick="savegridattr(\''+rowdata.inspectionGroupId+'\''+',\''+rowdata.itemHeaderId+'\')">'+ '明细'+ 'a>'
                },
            },

2.dialog框的定义(dialog框的定义不在 body内,他是其他页面的)


<div id="dialog11">
div>
<script>
    $("#dialog11").kendoWindow({
        width: "500px",
        height: "400px",
        title: '校验计划明细',
        modal: true,
        resizable: false,
        visible: false,
        iframe: true,
        close: function (e) {
            //$('#grid').data('kendoGrid').dataSource.page(1);
        }
    });
    function savegridattr(key) {
        var roleWin = $("#dialog11").data("kendoWindow");
        //这句就是,弹框访问的 url,带了参数的
        roleWin.refresh('http://localhost:8080/core_war_exploded/calb_od_inspection_assign/od_inspection_assign.html?inspectionGroupId='+key);
        if (parent.autoResizeIframe) {
            parent.autoResizeIframe('${RequestParameters.functionCode!}', 700, function () {
                roleWin.center().open();
            });
        } else {
            roleWin.center().open();
        }
    }
script>

3.在 url页面,即明细页面,需要接受 行传过来的,参数,并赋值给 明细的 viewModel
明细html
1.接受,参数

<script type="text/javascript">
    var viewModel = Hap.createGridViewModel("#grid");
    //这句话就是接受 行通过url 带来的参数
    var inspectionGroupId = "${RequestParameters.inspectionGroupId!'0'}";
    //这句也得加上,弹dialog框才会成功
    function back(){
        window.parent.$('#dialog11').data("kendoWindow").close();
    }
script>

2.赋值给,viewModel

//在 viewModel初始化的时候赋值
  parameterMap: function (options, type) {
                if (type !== "read" && options.models) {
                    var datas = Hap.prepareSubmitParameter(options, type)
                    return kendo.stringify(datas);
                } else if (type === "read") {
                    viewModel.model.set("inspectionGroupId",inspectionGroupId);
                    return Hap.prepareQueryParameter(viewModel.model.toJSON(), options)
                }
            }

最后注意这是 行和明细的新增没有完成)

在行script 和 明细script 的 parameterMap 的 插入时,一定要将,viewModel中插入对应的 头ID 和 明细ID 这样插入才算成功,不然下次 头点击 查询,或者查询明细的时候,还是查不到新插入的记录

 parameterMap: function (options, type) {
                if (type !== "read" && options.models) {
					//想法是在 这里 给 viewModel的 planId赋值
					//都是效果还是不显示
                    var datas = Hap.prepareSubmitParameter(options, type);
                    return kendo.stringify(datas);
                } else if (type === "read") {

                    return Hap.prepareQueryParameter(viewModelLine.model.toJSON(), options)
                }
            }

25.后台 如果要返回错误,那么就抛 mtException就可以,
hap项目功能总结,以及技术注意点_第1张图片
,主要是,消息code和message,底层会走 全局异常,全局异常方法回返回 R(里面最重要的就是 code , message ,),这时抛异常,在异常方法里面会 setSuccess = false的,对于code和message , 一般如果不要求消息编码,那只有message也可以,message的拿到,如果是有消息编码的话,那message也要通过api获取到。最终都是返回 R只是 R的 code,messge,suceess怎么封装的问题
hap项目功能总结,以及技术注意点_第2张图片
26.对于 kendoui前后端交互得数据主要注意两个位置
1.input查询框(查询)
2.grid表格数据(删除,修改,更新)
对于查询出来得 viewModel (有 所有后台传过来得 json字段,不管 grid中有没有 filed接收)
对于insert,新的记录 只有 filed字段和主键,这要区分清楚

input框和grid框得 viewModel 要区分开

27.数据校验
hap得数据校验,在查询时没有校验,在更新和插入时才数据校验了,所以对于查询的 非空字段,一般只考虑 搜索框,的必输项(前端的校验),或者到后台去,拿着dto去判断 null,不能说直接 在后台 jrs303校验,那对于 全表查就有影响了,当然视情况而定,这里说的 hap通用条件查询,即生成的,是没有做jrs303数据校验的

28.重置框(重置input框)

<span class="btn btn-default" style="float:left;" data-bind="click:reset" 
type="button"><i class="fa fa-eraser" style="margin-right:3px;">i>
<@spring.message "hap.reset"/>span>

29.时间lov(时间不能用lov,因为在lov中无法查 date数据类型)

 <input id="start" type="text" style="width: 100%"    data-role="datetimepicker"
               class="k-datetimepicker" data-bind="value:model.start(自定义的,后台用String start接收),events: {change: onChange}">input>
 <small class="help-block">开始时间small>

30.注意:因为很多表不能用作,全表查询,我们在后台常常要校验,哪些输入框的值 不能为 null 保证拼接sql的时候 一定会走 where 索引,但是有一个问题,就是我们进入页面的时候,一定是没有任何条件的,简单来说如果用 我们写的 查询接口,那 就会因为查询条件的里面的属性为null , 而报错直接返回前端错误信息(通常是 xxx 不能为null/ xxx必输项等),那么我们有解决办法,
我们现在的目的就是,当进入页面的 那个查询的时候,第一我们要查询,第二我们不能走全表查询
1.所以,我们创建一个 专门 进入页面的一页 调用的接口,这个接口只在进入页面的时候调用,而为了满足上面2个要求,那么我们可以自定义sql,就是我们自己写一段默认查询的数据,例如我们可以 写 sql是,where xxx = 一个具体的值,这样查出的数据 即走了索引,又做到了进页面有数据,只是说这个数据没啥用 不能代表什么,只是用作 解决 bug的

2.至于说 一个接口,将 进入页面,和 点击查询按钮而不带任何查询条件,将这两种条件分隔开,如果不在前端做 特别的设计,例如进入页面 我给后台带 特定的参数,代表我这是 进入页面的这种情况,那么 进入页面的 查询接口 和 无条件的 点击查询按钮的 查询接口时,前台传给后台的 参数没有任何区别,无法做任何判断,将这两种情况 隔离开

31.limit是不能解决 不走全表查询 而节省效率的,因为limit是 select筛选出记录后在limit的,所以不要想着 用limit来,解决因为不能走 where(即全表查询)情况下,用limit的限制 来 达到 少扫描记录达到 不走全表 的效果的

32.自定义数据类型 和 final 类的 比大小的区别 TODO

33.Json包 api 各种的情况 TODO

34.前后台除了业务外最头疼就是 TODO
1.controller 参数接收
2.Dao层 参数接收
3.前台传给后台数据的封装定义
4.前台接收后台返回的json的 解析处理以及使用

35.批量模糊查询

36.前端 查询框 传过来一个 用 ,隔开的String ,或传过来 一个 List况的处理方法(一般就是 String传多个值,就是批量查询处理的时候,还不是批量更新插入和批量删除,因为批量更新插入和删除,传过来的都是 List

1.直接传String ,如果在业务层代码不用,这个查询字段说,非得转换成 List 2.直接传 List

37.怎么样处理,前端批量String 用 ,隔开,无论是中文还是英文的 ,后台都能够处理,将String 转换成 List,而不会因为用户输入 中文,而导致程序报错 TODO

你可能感兴趣的:(oracle,数据库,java)