关于类型擦除\union表结构不一致问题的分析

  本文提到的类型擦除与java中的重载有关。我们先看一下重载的定义:重载是Java多态性的表现,是用统一的处理方式处理不同数据的机制。Java方法的重载,即方法具有相同的命名,但参数列表(类型或个数)不同。

  以下是我写的两个方法,用于将用户列表或不同类型用户列表的List加入包含收件人、主题、邮件正文的一个数据结构中。如下:

private void addEmailRecipients(FlowRunTime startFlowRunTime,
			List<String> userIds, ProcessContext context, List<Task> taskList) 
private void addEmailRecipients(FlowRunTime startFlowRunTime, List<Set<String>> userSetList, 
			ProcessContext context, List<Task> taskList)

  不仔细观察,参数列表是相似的,唯一的区别是第二个参数,方法1为List<String>、方法2为List<Set<String>>,我认为这样的参数列表是不同的,可以认定为重载。

  但在保存时,编译器报出如下错误:

Method addEmailRecipients(FlowRunTime, List<String>, ProcessContext, List<Task>) has the same erasure addEmailRecipients(FlowRunTime, List<E>, ProcessContext, List<E>) as another

method in type ProcessActivityService

  将has the same erasure等关键字搜索,有这样一篇文章叫《Java语法糖的味道:泛型与类型擦除》,文章来自与《深入理解Java虚拟机:JVM高级特性与最佳实践》 。

  文章主要讲了Java语法中泛型的实现。下面是我对上篇文章读后的简单总结:

泛型是一种将参数类型作为参数实现更广泛应用的一种机制,在C++、C#中有所谓模板与泛型的机制是相似的。Java中的泛型与其他语言的泛型实现机制不同,是一种基于擦除的伪泛型。比如List<String>与List<Integer>在代码编写期间是不同的,但在编译好的字节码文件中却都被转化为原生类型。我们知道JDK1.5出现之前类似泛型的实现是通过继续以及类型强转实现,在字节码文件中泛型好像又回到了JDK1.5出现之前。关于Java为什么使用这种机制实现泛型,不同的人有不同的解决,比如效率等。但比如我们上述代码中的两个方法,如我们将其中一个返回值改为其他类型,编译是可以通过的。文章又对所谓的特征签名(源码签名,只包含参数类型、个数等)和方法描述(字节码签名,包括参数列表和返回值、原生类型等)进行了解释。重载是根据字节码的特殊签名,而返回值不参与特殊签名;但原本报类型擦除错误的方法加上不同返回值却可以通过编译,这是因为只要两个具有不同方法描述的方法均可以存在于同一个字节码文件中,所以通过了编译。另外,文章还对为什么类型在编译后被擦除,我们却可以通过反射等机制得到其原始类型。这是因为类型擦除了code级别的字节码文件,但特殊签名中包含的元数据特殊签名保留了原始类型。

2.2.1) ERROR 1222 (21000): The used SELECT statements have a different number of columns :

  这是因为使用union的两个SQL语句产生的记录的表结构不一致. 必须是结构完全一致的记录集合才可以使用UNION.以上就是两个表的字段不一样导致。下面是我们使用的sql。这是一个查询所有代码工作的语句。前半部分是查询所有OA中的jbpm待办,而下半部分则是查询所有来自另外系统的待办工作。因为新需求需要在OA的jbpm待办中新增委托人、转交人等属性,而其他系统的待办工作则没有类似概念。两个UNION语句之间出现了表结构的不一致导致了上面的错误。

  解决方法:

‘‘ as newFiled
<select id="queryMyTodoTask" resultMap="ExecutionResultMap"  parameterType="com.fx.oa.module.bpm.workflow.api.shared.domain.ProcessExecutionEntity">
		SELECT
			pexec.id,
			ptask.taskId,
			ptask.activityName,
			ptask.substituteUserCode,
			pexec.processDefineId,
			pdefine.name,
			pexec.processInstanceId,
			pexec.tableName,
			pexec.formDefineId,
			pexec.pkValue,
			pexec.urgencyDegree,
			suser.userName as ‘createUserCode‘,
			pexec.createTime,
			pexec.active,
			pexec.status,
			pexec.id AS todoUrl,
			pexec.id AS relateid,
			pexec.id AS domain
		FROM
			t_bpm_process_task ptask
		LEFT OUTER JOIN t_bpm_process_execution pexec ON ptask.processExecutionId = pexec.id
		LEFT OUTER JOIN t_bpm_process_define pdefine ON pexec.processDefineId = pdefine.id
		LEFT OUTER JOIN t_sys_user suser ON pexec.createUserCode = suser.userCode and suser.accessControl=‘Y‘
		WHERE ptask.taskId IN (
			SELECT DISTINCT
				taskimpl.dbid_
			FROM
				jbpm4_task taskimpl
			LEFT OUTER JOIN jbpm4_participation participat ON taskimpl.dbid_ = participat.task_
			WHERE
				taskimpl.assignee_ = #{createUserCode}
			OR (taskimpl.assignee_ IS NULL
			AND participat.type_ = ‘candidate‘
			AND participat.userid_ = #{createUserCode})
		)
		AND ptask.STATUS = 0
		AND pexec.STATUS IN (1, 6,8)
		AND pexec.active = ‘Y‘
		<!--
		<if test="createUserCode != null and createUserCode !=‘‘">
            AND ptask.createUserCode = #{createUserCode}
		</if>
		  -->
		<if test="createUserName != null and createUserName !=‘‘">
            AND suser.userName LIKE ‘%‘ #{createUserName} ‘%‘  
		</if>
		<if test="name != null and name !=‘‘">
			AND pdefine.name LIKE ‘%‘ #{name} ‘%‘  
		</if>
		<if test="startCreateTime != null and startCreateTime !=‘‘">
			AND pexec.createTime <![CDATA[>= #{startCreateTime} ]]>   
		</if>
		<if test="endCreateTime != null and endCreateTime !=‘‘">
			AND pexec.createTime <![CDATA[<= #{endCreateTime}]]>    
		</if>
		UNION 
		SELECT 
			todo.p_relate_id AS id,
			todo.id AS taskId,
			todo.p_activity_name AS activityName ,
			todo.p_relate_id AS processDefineId,
			‘‘ as substituteUserCode,
			todo.p_task_name AS NAME ,
			todo.p_relate_id AS processInstanceId,
			todo.p_relate_id AS tableName,
			todo.p_relate_id AS formDefineId,
			todo.p_relate_id AS pkValue,
			todo.p_urgency_degree AS urgencyDegree ,
			todo.p_applicant_name AS createUserCode ,
			todo.p_applicant_time AS createTime ,
			‘Y‘ AS active,
			todo.p_urgency_degree AS STATUS ,
			todo.p_url AS todoUrl ,
			todo.id AS relateid ,
			todo.p_domain AS domain 
		FROM m_Todo todo
		where 1=1
		AND todo.p_approval_id = #{createUserCode}
		<if test="createUserName != null and createUserName !=‘‘">
            AND todo.p_applicant_name LIKE ‘%‘ #{createUserName} ‘%‘  
		</if>
		<if test="name != null and name !=‘‘">
			AND todo.p_task_name LIKE ‘%‘ #{name} ‘%‘  
		</if>
		<if test="startCreateTime != null and startCreateTime !=‘‘">
			AND todo.p_applicant_time <![CDATA[>= #{startCreateTime} ]]>   
		</if>
		<if test="endCreateTime != null and endCreateTime !=‘‘">
			AND todo.p_applicant_time <![CDATA[<= #{endCreateTime}]]>    
		</if>
		ORDER BY
			createTime DESC
	</select>
时间: 2024-10-08 12:59:46

关于类型擦除\union表结构不一致问题的分析的相关文章

kettle中源和目标表结构不一致的情况处理

创建数据仓库的过程中,往往会遇到这样的问题,例如:源表由于业务原因新增了字段,而ETL程序中是按照之前的源表结构进行抽取的,那么如果不重新构建ETL程序,新的指标就不会流入DW,问题如下图所示 创建了一个简单的输入输出 如下图所示,源表中有一个column3字段没有被匹配到 下面我们可以打开sql编辑器,看看该字段的类型,然后在目标表中增加该字段就好了 PS:注意要谨慎点击sql编辑器中的执行按钮,该按钮虽然会自动的给目标表添加对应于源表所需的字段,但是如果之前目标表有 注释内容什么的就会被这个

A表数据插入到B表(表结构不一致)

D_A  有E\F\H 3字段 D_B 有 A\B\C\D\E\ID 字段 将 D_B 个别字段插入到D_A  表 INSERT INTO  D_A(E,F,H) select B,A,ID from D_B

表结构变更后出现的ERROR OGG-01161 Bad column index (88)

2014-07-31 09:38:31 ERROR OGG-01668 PROCESS ABENDING. 2014-07-31 09:38:31 ERROR OGG-01161 Bad column index (88) specified for table WIP.WIP_PARAMETERS, max columns = 88. 网上有说是表结构不一致的.可是我已经细致比对了每一个字段.是一致的. 那为什么初始化同步就出问题呢? 应该是打补丁导致源端表结构发生了变化,比方添加了字段. 此

JBPM表结构

一,概述 JBPM全称--Java  Business PrcessManagerment(业务流程管理),它是覆盖了业务流程管理.工作流.服务协作等领域的一个开放的.灵活的.易扩展的可执行流程语言框架. 二,最大特色 (1)它的业务逻辑定义没有采用目前的一些规范,而是采用了它自己定义的Jboss Jbpm Process Definition Language(jpdl).jpdl任务一个业务流程可以被看作是一个UML状态图.jpdl认为一个业务流程可以被看作是一个UML状态图.jpdl就是详

Oracle复制表结构和表数据

一, 复制表结构及数据 create table z_xudebiao_test as select * from v_topic v where v.adddate > to_date('2016-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss'); 二, 复制表结构 create table z_xudebiao_test as select * from v_topic v where 1=2 或者 create table z_xudebiao_test l

mysql 复制表结构(包括索引等)、表内容

=============================================== 2019/7/16_第1次修改                       ccb_warlock =============================================== mysql库中有一张表查询要较大,最后采取的方案是清理数据只保留近期.但是有需要保留原表所有数据的备份,由此才尝试了复制表结构.表内容的sql脚本. 一.复制表结构(包括索引等) CREATE TABLE <

HBase -ROOT-和.META.表结构(region定位原理)

转自:http://blog.csdn.net/chlaws/article/details/16918913 在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操作的那个Region的RegionServer.Client本身并不知道哪个RegionServer管理哪个Region,那么它是如何找到相应的RegionServer的?本文就是在研究源

HBase -ROOT-和.META.表结构

在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操作的那个Region的RegionServer.Client本身并不知道哪个RegionServer管理哪个Region,那么它是如何找到相应的RegionServer的?本文就是在研究源码的基础上揭秘这个过程. 在前面的文章“HBase存储架构”中我们已经讨论了HBase基本的存储架构.在此基础上

SQLServer2005,2000获取表结构:字段名、类型、长度、主键、非空、注释

SQLServer 2005 SELECT d.name N'TableName', d.xtype N'TableType', a.colorder N'ColumnIndex', a.name N'ColumnName', (case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '1'else '0' end) N'IdnetityFG', (case when (SELECT count(*) FROM sysobjects