c标签foreach中循环split的值

最近做项目碰到一个问题,基本业务是这样子的:

有两张表,table1和table2,table2用来记录上传的文件信息如文件名称、文件地址等,table1用来记录文件上传的记录如上传人,上传时间等描述信息,它有一个字段用于保存文件序号(即table2的主键序号),可能是一个也可能是多个,现在需要将文件上传的信息及文件信息以文件为单位展示出来。

基本业务挺简单的,但对于习惯了用JSTL展示数据的我来说,处理起来就不那么简单了,以下为处理过程。

1、先建立基本数据用于测试

a、先建文件表:table2,

CREATE TABLE [dbo].[table2](
	[field1] [int] IDENTITY(1,1) NOT NULL,
	[field2] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
	[field3] [varchar](100) COLLATE Chinese_PRC_CI_AS NULL,
 CONSTRAINT [PK_table2] PRIMARY KEY CLUSTERED 
(
	[field1] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键序号' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'table2', @level2type=N'COLUMN', @level2name=N'field1'

GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'文件名称' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'table2', @level2type=N'COLUMN', @level2name=N'field2'

GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'文件路径' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'table2', @level2type=N'COLUMN', @level2name=N'field3'

--insert基础数据
INSERT INTO table2(field2,field3) VALUES('测试文件1','D:/temp/test1.pdf')
INSERT INTO table2(field2,field3) VALUES('测试文件2','D:/temp/test2.pdf')
INSERT INTO table2(field2,field3) VALUES('测试文件3','D:/temp/test3.pdf')
INSERT INTO table2(field2,field3) VALUES('测试文件4','D:/temp/test4.pdf')
INSERT INTO table2(field2,field3) VALUES('测试文件5','D:/temp/test5.pdf')
INSERT INTO table2(field2,field3) VALUES('测试文件6','D:/temp/test6.pdf')

b、再建文件上传记录表table1:

CREATE TABLE [dbo].[table1](
	[field1] [int] IDENTITY(1,1) NOT NULL,
	[field2] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
	[field3] [varchar](100) COLLATE Chinese_PRC_CI_AS NULL,
 CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED 
(
	[field1] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键序号' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'table1', @level2type=N'COLUMN', @level2name=N'field1'

GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'文件序号(即table2的主键序号),多个时以英文半角的逗号分开' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'table1', @level2type=N'COLUMN', @level2name=N'field2'

GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'描述' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'table1', @level2type=N'COLUMN', @level2name=N'field3'

--insert基础数据
INSERT INTO table1(field2,field3) VALUES('1','描述1')
INSERT INTO table1(field2,field3) VALUES('1,2,3,4','描述2')
INSERT INTO table1(field2,field3) VALUES('5,6,3','描述3')
INSERT INTO table1(field2,field3) VALUES('4,6','描述4')
INSERT INTO table1(field2,field3) VALUES('1,2,3,4,5','描述5')
INSERT INTO table1(field2,field3) VALUES('2','描述6')

2、写SQL语句将两个表中的信息弄到一起

select t1.field1 as '主键序号',t1.field3 as '描述',t1.field2 as '文件序号',
--len(t1.field2)-len(replace(t1.field2,',','')):为0时表示有一个文件 为1时表示有2个,依次类推
len(t1.field2)-len(replace(t1.field2,',','')) as '文件数量',
--有超过1个的文件时使用*号将文件名称分开
(case when (len(t1.field2)-len(replace(t1.field2,',','')))>0 then (select '*'+t2.field2 from table2 as t2 where CHARINDEX(','+LTRIM(t2.field1)+',',','+t1.field2+',')>0  for xml path(''))else (select t2.field2 from table2 as t2 where CHARINDEX(','+LTRIM(t2.field1)+',',','+t1.field2+',')>0 ) end) as '文件名称'
from table1 as t1 ; 

结果如下:

3、使用java代码进行查询

代码我也不写了,就说一下获取到的结果名称和格式:List<Object[]> fileList

4、页面展示:

先进行简单输出

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<table border="1">
<tr>
	<td>主键序号</td>
	<td>描述</td>
	<td>文件序号</td>
	<td>文件数量</td>
	<td>文件名称</td>
</tr>
<c:forEach items="${fileList }" var="file">
	<tr>  
		<td>{file[0]}</td><!--主键序号 -->
		<td>{file[1]}</td><!--描述-->
		<td>{file[2]}</td><!--文件序号-->
		<td>{file[3]}</td><!--文件数量-->
		<td>{file[4]}</td><!--文件名称-->
	</tr>
</c:forEach>
</table>

输出结果与上图相同,这里就不截图了。

很明显,这样子的结果是以table1的数据为主,而不是以文件为单位,一个文件一个文件的输出。以上图中的描述2为例子,若以table1为主,那么就是显示那一条记录,若是为文件为单位,应该是4条数据。因此需要根据文件序号或文件名称进行截取,然后再循环,这里需要用到fn标签里边的split函数。修改后的代码如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<table border="1">
<tr>
	<td>主键序号</td>
	<td>描述</td>
	<td>文件序号</td>
<!--	<td>文件数量</td>-->
	<td>文件名称</td>
</tr>
<c:forEach items="${fileList }" var="file">
	<c:choose>
		<c:when test="${file[3]>0 }"><!--file[3]表示文件数量,为0时说明有一个文件,0即有多个文件 -->
	 		<c:set value="${fn:split(file[4], '*') }" var="names" /><!--file[4]表示文件名称,以*号隔开 -->
	 		<c:set value="${fn:split(file[2], ',') }" var="ids" /><!--file[2]表示文件序号,以,号隔开 -->
			<c:forEach items="${names }" var="name" varStatus="indexes"><!--循环文件名称 -->
				<tr>
					<td>{file[0]}</td><!--主键序号 -->
					<td>{file[1]}</td><!--描述-->
					<td>{ids[indexes.index]}</td><!--文件序号-->
<!--				<td>{file[3]}</td>文件数量-->
					<td>{name}</td><!--文件名称-->
				</tr>
			</c:forEach>
		</c:when>
		<c:otherwise><!--说明只有一个,那么直接显示即可 -->
			<tr>
				<td>{file[0]}</td><!--主键序号 -->
				<td>{file[1]}</td><!--描述-->
				<td>{file[2]}</td><!--文件序号-->
<!--			<td>{file[3]}</td>文件数量-->
				<td>{file[4]}</td><!--文件名称-->
			</tr>
		</c:otherwise>
</c:forEach>
</table>

有时候会遇到文件名称过长需要截取的情况,处理如下

<c:set value="22" var="wordNum"/> <!---定义变量,用来说明要截取的字数--->
<!--<td>{name}</td>文件名称-->
<!--文件名称-->
<td>
	${fn:substring(name,0,(fn:length(name)>wordNum?wordNum:fn:length(name)))}
	<c:if test="${fn:length(name)>wordNum }">...</c:if>
</td>

最后,祝大家好运!

猜你喜欢

转载自1017401036.iteye.com/blog/2405291