ec:table的学习和总结

本文介绍如何通过引入ExtremeComponents库并配置web.xml来使用ec:table标签,简化JSP页面中表格数据的展示及操作,如排序、分页等功能。

首先,想使用ec:table必须引入<%@ taglib uri="http://www.extremecomponents.org" prefix="ec" %>

然后,就是要下载extremecomponents.tld 并正确在web.xml中配置(可以搜索关键字web.xml配置tld,也可以参考这篇文章http://blog.youkuaiyun.com/zhengcandan/article/details/4261906)


<ec:table action="viewProDisStat!unitListInfo.do" items="proList" var="pro"  retrieveRowsCallback="limit" >



//action是你要去请求的地址,排序时需要
//items是返回的结果集,类似c:forEach 中的items="${proDisList }"
//var 变量名
//retrieveRowsCallback 表示是否支持分页,不写只能向后翻页,不能向前翻页


<ec:row>


//类似table的tr


<ec:column property="opt" title="操作" sortable="false" viewsDenied="xls" style="text-align:center">


//ec:column 类似table的td ,内容为数字时可以直接使用<ec:column property="opt" title="操作" sortable="false" viewsDenied="xls" style="text-align:center"/>
//property 属性名,可以用于排序使用,要和数据库中字段保持一致
//title 要展现的字段名称
//sortable 是否可以排序,默认或者不写为true
//viewsDenied 制定类不允许使用的视图。视图包括:html、pdf、xls、csv,以及任何定制的视图。
//style html样式表


使用ec:table的好处是不用在自己去写点击事件,虽然也能实现,但有现成的为什么不用呢?
( { _id: ObjectId("673d5181437bad62e6577f61"), et: ISODate("2024-11-10T16:00:00.000Z"), bs: [ { bid: "f4eee9c8-a5c3-483f-881e-6fc1deb8ec95", f: NumberInt("2"), l: NumberInt("32"), p: NumberInt("176") } ], cs: [ { bid: "f4eee9c8-a5c3-483f-881e-6fc1deb8ec95", c: "86370040000080411011", l: NumberInt("3"), pc: null, t: ISODate("2024-11-10T16:00:00.000Z"), st: null, chd: "86370050000479285069,86370050000479274901,86370050000479299001,86370050000479315095,86370050000479326093,86370050000479300528", a: NumberInt("0"), fa: NumberInt("6"), s: NumberInt("0"), ec: null, f: NumberInt("0"), sf: NumberInt("0"), fc: null, fid: NumberInt("1"), x: null }, { bid: "f4eee9c8-a5c3-483f-881e-6fc1deb8ec95", c: "86370050000479285069", l: NumberInt("2"), pc: "86370040000080411011", t: ISODate("2024-11-10T16:00:00.000Z"), st: null, chd: "84246300015182823099,84246300015190754368,84246300015198424227,84246300015205872018,84246300015172072422,84246300015165400166,84246300015150253080,84246300015907212709,84246300015218134180,84246300015850111361,84246300015846591079,84246300015182860777,84246300015148654584,84246300015218825195,84246300015163342140,84246300016138228446,84246300015175930307,84246300015932811155,84246300015927021437,84246300015922563176,84246300014986950029,84246300015239451811,84246300015225806887,84246300015248510824,84246300015096106699,84246300015105504114,84246300015934926672,84246300015889876704,84246300015898064401,84246300015233585289,84246300015374090794,84246300015298644226,84246300015402549992,84246300015649493176,84246300015407807454,84246300015416172613,84246300015424509992,84246300015431088300,84246300015975482047,84246300015982900214", a: NumberInt("0"), fa: NumberInt("40"), s: NumberInt("0"), ec: null, f: NumberInt("0"), sf: NumberInt("0"), fc: null, fid: NumberInt("1"), x: null }] CREATE TABLE `ods.ods_ac_mongo_coderelations`( `_id` string DEFAULT NULL, `et` timestamp DEFAULT NULL, `bs` array<struct<bid:string,f:int,l:int,p:int>> DEFAULT NULL, `cs` array<struct<bid:string,c:string,l:int,pc:string,t:timestamp,st:string,chd:string,a:int,fa:int,s:int,ec:string,f:int,sf:int,fc:string,fid:int,x:string>> DEFAULT NULL )一行一个批次 有可能有合批 bs有两个bid 目前已经把mongodb里这种数据存到关系型数据库ods_ac_mongo_coderelations表里,但是想把bscs里的数据取出来放到新的表里 表结构怎么设计 sql怎么写
09-27
<think>我们已知源表为关系型数据库中的表:ods_ac_mongo_coderelations,其中包含bscs字段(存储的是JSON数组格式的数据)。 目标:将bscs字段的数据提取到新表中,并设计新表的结构。 根据之前的讨论,bscs都是数组,每个元素是一个对象。我们需要将数组拆分为行(即一行一个元素),同时保留与主文档的关联。 设计思路: 1. 创建一个主表(或保持原表)存储公共字段(如_id, et等),但用户要求只提取bscs字段,所以我们可以创建两个新表分别存储bscs的明细数据。 2. 由于bscs中的每个对象都有多个属性,我们将这些属性作为新表的列。 具体表结构设计: 表1:bs_detail - id: 自增主键(可选,也可以使用复合主键) - main_id: 关联原表的主键(即原表的主键,假设原表有主键id,或者是原表中的_id字段,但原表中的_id是MongoDB的ObjectId,在关系型数据库中可能已经映射为字符串或二进制) - bid: 字符串类型(对应bs中的bid) - f: 整数类型(对应bs中的f) - l: 整数类型(对应bs中的l) - p: 整数类型(对应bs中的p) 表2:cs_detail - id: 自增主键(可选) - main_id: 关联原表的主键 - bid: 字符串类型(对应cs中的bid) - c: 字符串类型(对应cs中的c) - l: 整数类型(对应cs中的l) - pc: 字符串类型(对应cs中的pc,可为空) - t: 时间戳类型(对应cs中的t) - st: 时间戳类型(可为空,对应cs中的st) - chd: 文本类型(对应cs中的chd,因为可能较长) - a: 整数类型(对应cs中的a) - fa: 整数类型(对应cs中的fa) - s: 整数类型(对应cs中的s) - ec: 字符串类型(可为空,对应cs中的ec) - f: 整数类型(对应cs中的f) - sf: 整数类型(对应cs中的sf) - fc: 字符串类型(可为空,对应cs中的fc) - fid: 整数类型(对应cs中的fid) - x: 字符串类型(可为空,对应cs中的x) 注意:原表(ods_ac_mongo_coderelations)中必须有一个唯一标识每行的主键(假设为main_id),用于关联这两个明细表。 如果原表没有主键,那么我们可能需要使用原表中的_id字段(它是MongoDB的ObjectId,在关系型数据库中可能是字符串类型)作为关联字段。 假设原表结构: ods_ac_mongo_coderelations ( _id VARCHAR(24) PRIMARY KEY, -- 或者是一个自增主键,但这里我们假设_id是主键 et TIMESTAMP, bs JSON, -- 存储bs数组 cs JSON -- 存储cs数组 ) 那么,我们需要创建两个新表,并编写SQL将bscs数组拆分为行。 由于不同的关系型数据库处理JSON的函数不同,这里以PostgreSQL为例(如果使用MySQL,则需要使用JSON_TABLE函数,但MySQL5.7以上支持,而PostgreSQL有jsonb_array_elements)。 以下是PostgreSQL的SQL示例: 步骤1:创建bs_detail表 ```sql CREATE TABLE bs_detail ( id SERIAL PRIMARY KEY, main_id VARCHAR(24) NOT NULL REFERENCES ods_ac_mongo_coderelations(_id), bid VARCHAR(50), f INTEGER, l INTEGER, p INTEGER ); ``` 步骤2:创建cs_detail表 ```sql CREATE TABLE cs_detail ( id SERIAL PRIMARY KEY, main_id VARCHAR(24) NOT NULL REFERENCES ods_ac_mongo_coderelations(_id), bid VARCHAR(50), c VARCHAR(50), l INTEGER, pc VARCHAR(50), t TIMESTAMP, st TIMESTAMP, chd TEXT, a INTEGER, fa INTEGER, s INTEGER, ec VARCHAR(50), f INTEGER, sf INTEGER, fc VARCHAR(50), fid INTEGER, x VARCHAR(50) ); ``` 步骤3:从原表导入bs数据到bs_detail 使用jsonb_array_elements函数(如果原表是jsonb类型)或者json_array_elements(如果原表是json类型): ```sql INSERT INTO bs_detail (main_id, bid, f, l, p) SELECT _id AS main_id, elem->>'bid' AS bid, (elem->>'f')::INTEGER AS f, (elem->>'l')::INTEGER AS l, (elem->>'p')::INTEGER AS p FROM ods_ac_mongo_coderelations, LATERAL jsonb_array_elements(bs::jsonb) AS elem; ``` 注意:如果原表的bs字段是字符串类型,我们需要先转换为jsonb。如果已经是jsonb类型,则直接使用。 步骤4:从原表导入cs数据到cs_detail ```sql INSERT INTO cs_detail (main_id, bid, c, l, pc, t, st, chd, a, fa, s, ec, f, sf, fc, fid, x) SELECT _id AS main_id, elem->>'bid' AS bid, elem->>'c' AS c, (elem->>'l')::INTEGER AS l, elem->>'pc' AS pc, (elem->>'t')::TIMESTAMP AS t, (elem->>'st')::TIMESTAMP AS st, -- 注意:st可能为null,转换时需注意 elem->>'chd' AS chd, (elem->>'a')::INTEGER AS a, (elem->>'fa')::INTEGER AS fa, (elem->>'s')::INTEGER AS s, elem->>'ec' AS ec, (elem->>'f')::INTEGER AS f, (elem->>'sf')::INTEGER AS sf, elem->>'fc' AS fc, (elem->>'fid')::INTEGER AS fid, elem->>'x' AS x FROM ods_ac_mongo_coderelations, LATERAL jsonb_array_elements(cs::jsonb) AS elem; ``` 注意: 1. 对于可能为null的字段(如st, pc, ec, fc, x等),直接使用->>会得到字符串的null,转换为时间戳或整数会失败。我们可以使用NULLIF函数: 例如:NULLIF(elem->>'st', 'null')::TIMESTAMP 或者更通用的,判断是否为null字符串,但PostgreSQL中jsonb_array_elements展开后,如果原字段是null,则->>返回的是空字符串?还是字符串'null'?实际上,在JSON中,null值在转换为文本时是字符串'null'。但为了安全,我们可以使用: CASE WHEN elem->'st' IS NULL OR jsonb_typeof(elem->'st') = 'null' THEN NULL ELSE (elem->>'st')::TIMESTAMP END 2. 如果原表数据量很大,考虑分批插入。 对于MySQL 8.0以上版本,可以使用JSON_TABLE函数,示例: 插入bs_detail(MySQL): ```sql INSERT INTO bs_detail (main_id, bid, f, l, p) SELECT _id AS main_id, j.bid, j.f, j.l, j.p FROM ods_ac_mongo_coderelations, JSON_TABLE(bs, '$[*]' COLUMNS ( bid VARCHAR(50) PATH '$.bid', f INT PATH '$.f', l INT PATH '$.l', p INT PATH '$.p' )) AS j; ``` 类似地,插入cs_detail(MySQL): ```sql INSERT INTO cs_detail (main_id, bid, c, l, pc, t, st, chd, a, fa, s, ec, f, sf, fc, fid, x) SELECT _id AS main_id, j.bid, j.c, j.l, j.pc, j.t, j.st, j.chd, j.a, j.fa, j.s, j.ec, j.f, j.sf, j.fc, j.fid, j.x FROM ods_ac_mongo_coderelations, JSON_TABLE(cs, '$[*]' COLUMNS ( bid VARCHAR(50) PATH '$.bid', c VARCHAR(50) PATH '$.c', l INT PATH '$.l', pc VARCHAR(50) PATH '$.pc', t TIMESTAMP PATH '$.t', st TIMESTAMP PATH '$.st', chd TEXT PATH '$.chd', a INT PATH '$.a', fa INT PATH '$.fa', s INT PATH '$.s', ec VARCHAR(50) PATH '$.ec', f INT PATH '$.f', sf INT PATH '$.sf', fc VARCHAR(50) PATH '$.fc', fid INT PATH '$.fid', x VARCHAR(50) PATH '$.x' )) AS j; ``` 注意:MySQL中时间戳的处理,如果JSON中的时间是字符串,需要确保格式正确。 总结: 1. 新表结构按照bscs中的字段设计,每个字段根据其含义选择合适的数据类型。 2. 使用数据库的JSON解析函数将数组拆分为行,并插入新表。 如果原表没有主键,我们需要先确保有一个唯一标识每行的字段(比如添加自增主键,或者使用原表的_id)。 最后,根据实际数据库类型(PostgreSQL, MySQL, SQL Server等)选择合适的JSON解析方法。 注意:在迁移过程中,需要处理JSON解析可能出现的错误(如字段缺失、类型不匹配等),可以添加异常处理或使用条件表达式。 如果某个字段在JSON对象中不存在,则解析为NULL。 生成的相关问题: 1. 如何在不同类型的数据库(如MySQL、PostgreSQL、SQL Server)中解析JSON数组? 2. 在迁移过程中如何处理JSON字段中的空值或格式错误? 3. 如果bs或cs数组非常大,如何优化迁移性能? 4. 新表结构是否需要添加索引以提高查询效率? 5. 如何验证迁移后数据的完整性准确性? </think>### 新表结构设计与SQL语句 #### 表结构设计思路 1. **数据扁平化处理**:将嵌套的JSON数组拆分为关系型表结构 2. **保留关联关系**:通过主键关联保证数据完整性 3. **字段类型映射**:根据MongoDB字段特性选择合适的关系型字段类型 #### 新表设计方案 ```sql -- 批次表 (存储bs字段数据) CREATE TABLE batch_records ( id BIGINT PRIMARY KEY AUTO_INCREMENT, -- 自增主键 main_id CHAR(24) NOT NULL, -- 关联主文档ID bid VARCHAR(36) NOT NULL, -- 批次ID (UUID格式) f_level INT NOT NULL, -- f字段 (层级) l_count INT NOT NULL, -- l字段 (数量) p_value INT NOT NULL, -- p字段 (参数值) created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 代码关系表 (存储cs字段数据) CREATE TABLE code_relations ( id BIGINT PRIMARY KEY AUTO_INCREMENT, -- 自增主键 main_id CHAR(24) NOT NULL, -- 关联主文档ID batch_id VARCHAR(36) NOT NULL, -- 关联批次ID code VARCHAR(24) NOT NULL, -- c字段 (代码) l_level INT NOT NULL, -- l字段 (层级) parent_code VARCHAR(24), -- pc字段 (父代码) event_time TIMESTAMP NOT NULL, -- t字段 (时间) children TEXT, -- chd字段 (子代码列表) a_value INT NOT NULL DEFAULT 0, -- a字段 fa_count INT NOT NULL DEFAULT 0, -- fa字段 s_value INT NOT NULL DEFAULT 0, -- s字段 fid_value INT NOT NULL DEFAULT 0, -- fid字段 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 创建索引优化查询 CREATE INDEX idx_main_id ON batch_records(main_id); CREATE INDEX idx_batch_id ON code_relations(batch_id); CREATE INDEX idx_code_relations_main ON code_relations(main_id); ``` #### 数据提取SQL语句 (PostgreSQL示例) ```sql -- 提取bs字段数据到batch_records表 INSERT INTO batch_records (main_id, bid, f_level, l_count, p_value) SELECT _id AS main_id, elem->>'bid' AS bid, (elem->>'f')::INTEGER AS f_level, (elem->>'l')::INTEGER AS l_count, (elem->>'p')::INTEGER AS p_value FROM ods_ac_mongo_coderelations, LATERAL jsonb_array_elements(bs::jsonb) AS elem; -- 提取cs字段数据到code_relations表 INSERT INTO code_relations ( main_id, batch_id, code, l_level, parent_code, event_time, children, a_value, fa_count, s_value, fid_value ) SELECT _id AS main_id, elem->>'bid' AS batch_id, elem->>'c' AS code, (elem->>'l')::INTEGER AS l_level, NULLIF(elem->>'pc', 'null') AS parent_code, (elem->>'t')::TIMESTAMP AS event_time, elem->>'chd' AS children, COALESCE((elem->>'a')::INTEGER, 0) AS a_value, COALESCE((elem->>'fa')::INTEGER, 0) AS fa_count, COALESCE((elem->>'s')::INTEGER, 0) AS s_value, COALESCE((elem->>'fid')::INTEGER, 0) AS fid_value FROM ods_ac_mongo_coderelations, LATERAL jsonb_array_elements(cs::jsonb) AS elem; ``` #### MySQL兼容方案 ```sql -- MySQL提取bs字段 INSERT INTO batch_records (main_id, bid, f_level, l_count, p_value) SELECT t._id, JSON_EXTRACT(j.value, '$.bid'), JSON_EXTRACT(j.value, '$.f'), JSON_EXTRACT(j.value, '$.l'), JSON_EXTRACT(j.value, '$.p') FROM ods_ac_mongo_coderelations t, JSON_TABLE(t.bs, '$[*]' COLUMNS ( value JSON PATH '$' )) AS j; -- MySQL提取cs字段 INSERT INTO code_relations (main_id, batch_id, code, l_level, parent_code, event_time, children, a_value, fa_count, s_value, fid_value) SELECT t._id, JSON_UNQUOTE(JSON_EXTRACT(j.value, '$.bid')), JSON_UNQUOTE(JSON_EXTRACT(j.value, '$.c')), JSON_EXTRACT(j.value, '$.l'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(j.value, '$.pc')), 'null'), JSON_UNQUOTE(JSON_EXTRACT(j.value, '$.t')), JSON_UNQUOTE(JSON_EXTRACT(j.value, '$.chd')), COALESCE(JSON_EXTRACT(j.value, '$.a'), 0), COALESCE(JSON_EXTRACT(j.value, '$.fa'), 0), COALESCE(JSON_EXTRACT(j.value, '$.s'), 0), COALESCE(JSON_EXTRACT(j.value, '$.fid'), 0) FROM ods_ac_mongo_coderelations t, JSON_TABLE(t.cs, '$[*]' COLUMNS ( value JSON PATH '$' )) AS j; ``` ### 关键设计说明 1. **层级关系处理**: - `f_level``l_level`保留原始层级信息 - `parent_code`存储父节点关联关系 - `children`字段存储逗号分隔的子节点列表 2. **空值处理策略**: ```sql NULLIF(elem->>'pc', 'null') -- 将JSON中的'null'转为SQL NULL COALESCE((elem->>'a')::INTEGER, 0) -- 空值转为0 ``` 3. **性能优化**: - 使用`LATERAL JOIN`提升JSON解析效率 - 创建索引加速关联查询 - 批量插入减少事务开销 4. **数据类型映射**: | MongoDB类型 | 关系型类型 | 处理方式 | |------------|------------|---------| | ObjectId | CHAR(24) | 直接存储 | | ISODate | TIMESTAMP | 自动转换 | | NumberInt | INTEGER | 类型转换 | ### 数据验证查询 ```sql -- 检查数据完整性 SELECT (SELECT COUNT(*) FROM batch_records) AS batch_count, (SELECT COUNT(*) FROM code_relations) AS relation_count; -- 验证层级关系 SELECT c.code, c.parent_code, b.bid FROM code_relations c JOIN batch_records b ON c.batch_id = b.bid WHERE c.l_level = 2; ``` ### 嵌套JSON处理建议 对于`chd`字段中的逗号分隔值,建议在应用层处理或在ETL过程中进一步拆分: ```sql -- 可选:创建子代码关系表 CREATE TABLE child_codes ( id BIGINT PRIMARY KEY AUTO_INCREMENT, relation_id BIGINT NOT NULL, child_code VARCHAR(24) NOT NULL, FOREIGN KEY (relation_id) REFERENCES code_relations(id) ); -- 拆分chd字段的SQL INSERT INTO child_codes (relation_id, child_code) SELECT cr.id, TRIM(REGEXP_SPLIT_TO_TABLE(cr.children, ',')) FROM code_relations cr; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值