delphi枚举类型值的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi枚举类型值的问题相关的知识,希望对你有一定的参考价值。

代码如下type MyEnum=(meval1,meval2,meval3=0);vare:MyEnumbegine:=meval1;writeln(ord(e)); //显示0e:=meval3;writeln(ord(e)); //显示0writeln(ord(low(e))): //显示0writeln(ord(high(e))): //显示1readln;end在writeln(ord(low(e))): 的时候,输出的是0,但是在writeln(ord(high(e))): 的时候,显示的为什么是1?这个枚举类型的三种取值meval1,meval2,meval3,序号难道不都是0么?

参考技术A test.dpr.18: e:=meval1;
0040A179 33DB xor ebx,ebx
test.dpr.20: writeln(ord(e)); //显示0
0040A17B 0FB6D3 movzx edx,bl
0040A17E A14CBC4000 mov eax,[$0040bc4c]
0040A183 E88098FFFF call @Write0Long
0040A188 E8A798FFFF call @WriteLn
0040A18D E8828FFFFF call @_IOTest
test.dpr.22: e:=meval3;
0040A192 33DB xor ebx,ebx
test.dpr.24: writeln(ord(e)); //显示0
0040A194 0FB6D3 movzx edx,bl
0040A197 A14CBC4000 mov eax,[$0040bc4c]
0040A19C E86798FFFF call @Write0Long
0040A1A1 E88E98FFFF call @WriteLn
0040A1A6 E8698FFFFF call @_IOTest
test.dpr.26: writeln(ord(low(e))); //显示0
0040A1AB A14CBC4000 mov eax,[$0040bc4c]
0040A1B0 33D2 xor edx,edx
0040A1B2 E85198FFFF call @Write0Long
0040A1B7 E87898FFFF call @WriteLn
0040A1BC E8538FFFFF call @_IOTest
test.dpr.28: writeln(ord(high(e))); //显示1
0040A1C1 A14CBC4000 mov eax,[$0040bc4c]
0040A1C6 BA01000000 mov edx,$00000001
0040A1CB E83898FFFF call @Write0Long
0040A1D0 E85F98FFFF call @WriteLn
这是对应的汇编代码, low(e), high(e)都是直接赋值0, 1的

用typehandler优雅的解决枚举类型的读写

问题

  1. 当数据库表字段是枚举类型的码值的时候,往往要根据字段注释找对应的业务值。随着业务的发展,产生了新的码值,而数据库表的注释往往不会跟着变。新的码值的业务含义就很难知道了。
  2. 对应的DO类的字段亦是如此。有了新的码值,字段的注释一般跟不上。

解决办法

表字段是码值的时候,一般会有一个枚举(enum)类对应。我们可以把DO类的对应字段定义为枚举类型,用mybatis的typehandler来处理读写。
这样做之后,就只需要维护枚举类型,数据库字段和DO类的注释都不需要了。最好的注释就是对应的枚举类
通过枚举类强管控码值的变化,就不会随着时间的推移,代码的可读性和可维护性大大降低了。

具体做法

1 枚举字段类型定义, 我们的目标是直接把这个类型入库,并正确的读取出来。

public enum TerminalEnum 
	
	HTTP("http", "http接口"),
	DUBBO("dubbo", "dubbo接口"),
	WEB("web", "网页"),
	;
	
	TerminalEnum(String t, String n) 
		this.type = t;
		this.name = n;
	
	
	@Override
	public String toString() 
		return this.name;
	
	
	@Getter
	private String type;
	@Getter
	private String name;
	
	public static TerminalEnum getEnumByType(String type) 
		TerminalEnum[] values = TerminalEnum.values();
		for (TerminalEnum terminalEnum : values) 
			if (StringUtils.equalsIgnoreCase(type, terminalEnum.type)) 
				return terminalEnum;
			
		
		return null;
	


2 typehandler定义, 需要继承 org.apache.ibatis.type.BaseTypeHandler

读写的逻辑

  1. 写的时候取枚举的type字段
  2. 读的时候根据type字段转成枚举类型
public class TerminalEnumHandler extends BaseTypeHandler<TerminalEnum> 
	
	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, TerminalEnum terminalEnum, JdbcType jdbcType) throws SQLException 
		if (terminalEnum == null) 
			return;
		
		
		// 入库的时候取枚举的type字段
		ps.setString(i, terminalEnum.getType());
	
	
	@Override
	public TerminalEnum getNullableResult(ResultSet rs, String columnName) throws SQLException 
		String type = rs.getString(columnName);
		if (StringUtils.isBlank(type)) 
			return null;
		 else 
			// 读的时候根据type字段转成枚举类型
			return TerminalEnum.getEnumByType(type);
		
	
	
	@Override
	public TerminalEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException 
		String type = rs.getString(columnIndex);
		if (StringUtils.isBlank(type)) 
			return null;
		 else 
			return TerminalEnum.getEnumByType(type);
		
	
	
	@Override
	public TerminalEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException 
		String type = cs.getString(columnIndex);
		if (StringUtils.isBlank(type)) 
			return null;
		 else 
			return TerminalEnum.getEnumByType(type);
		
	

3 我的应用不需要手动注册这个typehandler
4 resultMap对应的字段加上typehandler

<resultMap id="BaseResultMap" type="com.***.***DO" >
... ... 
	<result column="terminal" property="terminal"  typeHandler="com.***.typehandler.TerminalEnumHandler"/>
</resultMap>

5 insert或者update的时候需要在字段后面带上typehandler

	<update id="updateTerminal" >
		UPDATE  ***_token
		SET
		terminal=#terminal, typeHandler=com.***.typehandler.TerminalEnumHandler
		WHERE id=#id
	</update>

以上是关于delphi枚举类型值的问题的主要内容,如果未能解决你的问题,请参考以下文章

delphi 枚举类型

delphi中枚举类型和子界,数组,集合的详解以及类型说明

Delphi基础-数据类型

DELPHI中枚举类型数据的介绍和使用方法

Delphi基本类型--枚举 子界 集合 数组

如何使用 Delphi 6 迭代初始化的枚举类型并避免“越界”错误?