ADempiere TableDirect类型的reference分析
透过采购单"仓库"下拉列表框显示过程,分析"TableDirect"类型的reference
看到采购单的仓库列表的列的显示格式,只是设置为了"TableDirect"的reference,这个reference没有什么进一步的设置,比如表明,列明,等等,心生好奇,看我来给大家找出其中缘由!
1.获得下拉列表数据SQL的生成
下面是窗口初始化时生成下拉框时候的调用堆栈,下拉框数据的大部分SQL就是这时候生成的
MLookupFactory.getLookup_TableDir(Properties, Language, int, String) line: 624
MLookupFactory.getLookupInfo(Properties, int, int, int, Language, String, int, boolean, String) line: 192
GridFieldVO.initFinish() line: 504
GridFieldVO.create(Properties, int, int, int, int, boolean, ResultSet) line: 201
GridTabVO.createFields(GridTabVO) line: 272
GridTabVO.getFields() line: 444
GridTab.loadFields() line: 353
GridTab.loadTab() line: 296
GridTab.initTab(boolean) line: 287
GridWindow.initTab(int) line: 195
APanel.initPanel(int, int, MQuery) line: 753
AWindow.initWindow(int, MQuery) line: 102
AMenuStartItem.startWindow(int, int) line: 249
AMenuStartItem.run() line: 147
"TableDirect"类型的reference,下拉列表框数据的SQL生成过程如下:
1.1根据数据库列名:M_Warehouse_ID, 得到键值列名M_Warehouse_ID和表名M_Warehouse,期间如果此列不是以"_ID"结尾则会报错
- 列名检察
- 得到列名
- 得到表名
getZoomTableName():
对于本例, 键值列名M_Warehouse_ID, 表明M_Warehouse
1.2取出表中"Identifier"的列
- 表定义如下:
- 最后根据表的列定义,拼为下面形式的sql:
NVL(%tableName%.col1Name,'-1')||'_'||NVL(%tableName%.col2Name,'-1')||'_'||NVL(%tableName%.col3Name,'-1')
取"Identifier"的SQL
SELECT c.ColumnName,c.IsTranslated,c.AD_Reference_ID,
c.AD_Reference_Value_ID,t.AD_Window_ID,t.PO_Window_ID , c.ColumnSQL
FROM adempiere.AD_Table t
INNER JOIN adempiere.AD_Column c ON (t.AD_Table_ID=c.AD_Table_ID)
WHERE TableName='M_Warehouse' AND c.IsIdentifier='Y' ORDER BY c.SeqNo
对于本例,因为M_Warehouse表只定义了一个Identifier列,就是'name'列,因此结果为NVL(M_Warehouse.name,'-1')
1.3.本例的最后结果为
select
M_Warehouse.M_Warehouse_ID, //tableName.keyColName
NULL, //固定的,和后面取数据方式有关
NVL(M_Warehouse.name,'-1'), //2步骤得到的SQL
M_Warehouse.IsActive //固定的
from M_Warehouse //from tableName
2.从数据库根据上面SQL查询数据并填充下拉列表 2.1.有3种情况,会触发:
- l 窗口第一次初始化
MLookup.loadData(boolean) line: 618
MLookup.getData(boolean, boolean) line: 370
MLookup.getData(boolean, boolean, boolean, boolean) line: 400
MLookup(Lookup).fillComboBox(boolean, boolean, boolean, boolean) line: 282
VLookup.<init>(String, boolean, boolean, boolean, Lookup) line: 281
VEditorFactory.getEditor(GridTab, GridField, boolean) line: 139
GridController.init() line: 416
GridController.initGrid(GridTab, boolean, int, APanel, GridWindow, boolean) line: 376
APanel.initPanel(int, int, MQuery) line: 808
AWindow.initWindow(int, MQuery) line: 102
AMenuStartItem.startWindow(int, int) line: 249
AMenuStartItem.run() line: 147
- l 刷新(右键->重新查询)
MLookup.loadData(boolean) line: 618
MLookup.getData(boolean, boolean) line: 370
MLookup.getData(boolean, boolean, boolean, boolean) line: 400
MLookup(Lookup).fillComboBox(boolean, boolean, boolean, boolean) line: 282
MLookup.refresh(boolean) line: 598
MLookup.refresh() line: 573
VLookup.actionRefresh() line: 1471
VLookup.actionPerformed(ActionEvent) line: 741
CMenuItem(AbstractButton).fireActionPerformed(ActionEvent) line: 1995
AbstractButton$Handler.actionPerformed(ActionEvent) line: 2318
DefaultButtonModel.fireActionPerformed(ActionEvent) line: 387
- l 更改采购单上的"组织"字段,并将焦点移动到仓库字段时,会根据当前新的组织去获得仓库列表
MLookup.loadData(boolean) line: 618
MLookup.getData(boolean, boolean) line: 382
MLookup.getData(boolean, boolean, boolean, boolean) line: 400
MLookup(Lookup).fillComboBox(boolean, boolean, boolean, boolean) line: 282
VLookup.focusGained(FocusEvent) line: 1510
2.2.获取数据MLookup$MLoader.run()
l 基于前面获得的SQL,加上一些条件限制,比如组织ID等,本例最后SQL如下:
SELECT M_Warehouse.M_Warehouse_ID,NULL,COALESCE(M_Warehouse.Name,'-1'),M_Warehouse.IsActive
FROM adempiere.M_Warehouse
WHERE M_Warehouse.AD_Client_ID IN(0,11)
AND M_Warehouse.AD_Org_ID IN(50007,0,50004,50005,50006,1000000,50000,50001,50002,11,12)
AND M_Warehouse.M_Warehouse_ID NOT IN (
SELECT Record_ID FROM adempiere.AD_Private_Access WHERE AD_Table_ID = 190 AND AD_User_ID <> 101 AND IsActive = 'Y' )
AND M_Warehouse.AD_Org_ID=50001 ORDER BY 3
上面的"COALESCE"不是前面的"NVL",这应该是我测试的时候用了postgresql的结果,中间进行了转换
l 从上面SQL结果中取出第一列(数字)或者第二列(字符)作为key,第3列作为name,放进一个map中,返回给前面显示下拉列表
代码说明:
boolean isNumber = m_info.KeyColumn.endsWith("_ID");
本例中是取出第一列和第三列,第二列在其他功能中应该会用到,就是key是字符的时候
3.分析结果
从上面可分析出,如果想让reference位tableDirect类型的列能显示出下拉列表的数据,则必须满足下面条件:
- 列名必须以"_ID"位结尾,且区分大小写,否则报错
- 从列名去掉后面的"_ID"得到的是存放列表数据的那个表的表名,从AD的命名规则来看,这个应该没问题
- 这个表必须至少有一列定义为"Identifier"列,否则会报错
- 这个表必须有"IsActive"列,否则会报SQL错误, 这个按照AD表的规则,应该没问题
- 最后下拉列表的key是那个表的主键,显示的是"Identifier"拼出来的列的值
好了,通过上面的分析,我们机会看到,为什么AD简单的使用了一个"TableDirect"的reference就能出个下拉列表,这需要建立在上面的一系列规则之上,否则的话就会出错喽!
转载于:https://blog.51cto.com/newmoon/988142
ADempiere TableDirect类型的reference分析相关推荐
- Java常见异常类型及原因分析
Java常见异常类型及原因分析 0x1 NullPointerException异常 顾名思义,NullPointerException 是空指针异常.但是在 Java 中没有指针,怎么会有 空指针异 ...
- 我的游戏学习日志13——类型游戏的分析(1)
我的游戏学习日志13--类型游戏的分析(1) 1.动作游戏(ACT)的分析 Action Game,最早出现的游戏类型,衍生出如FTG.STG.FPS.SPT等不同的子类别.游戏性大都单一,一般考验玩 ...
- JavaScript 特有奇葩问题“字符串类型与数字类型混乱”的分析与解决,与类型转换
字符串类型与数字类型的混乱,应该是JS最著名的奇葩问题了. 恰好最近遇到这个问题,在这里对这个问题的解决方法及产生原因进行总结与分析. Java 语言与 JavaScript 语言是什么关系.这是初学 ...
- linux应用日志类型,linux日志分析
linux的日志文件可以说是最有用的了,日志文件可以让我们了解系统所处的状态,比如能查出哪些用户有登入,这也涉及相关的安全问题. 日志分析 1.了解日志文件 linux的日志文件可以说是最有用的了,日 ...
- 《Essential C++》笔记之传引用(pass by reference)分析
参考博文:C++中,传值.传地址.传引用究竟有何区别 参考博文:C++作用域.局部变量.全局变量.传引用传值对比的一个例子 举例分析:把引用作为函数参数传递 bool fibon_elem(int,i ...
- 计算机组成原理复习要点与考题类型--选择-填空-分析-计算-简答
目录 选择题 填空题 分析判断题 计算题 简述题 选择题 1 . 某机字长32位,其中1位表示符号位.若用定点整数表示,则最小负整数为( ). A -(231 -1) B -(230 ...
- 关于VB提示ByRef参数类型不符的分析
在VB中执行过程或函数时,提示"ByRef参数类型不符" 分析问题主要由于对应参数的类型不符造成的.造成这种情况一般有几种情况: 1.传递参数未定义类型,如果参数在调用前未定义类型 ...
- Solidity的函数类型以及可见性分析(类比Java)
函数类型 函数也是一种类型(值类型),它是函数的调用方式.函数类型可以被赋值吗,作为参数和返回结果.函数可以分为两类:内部函数(Internal)和外部函数(External). 内部函数Intern ...
- 算法交易的主要类型与策略分析
2017-09-05 11:34 算法交易起源于上世纪中叶的配对交易 历史上最早使用算法交易的例子可以追溯到1949年.对冲基金之父阿尔弗雷德·琼斯,利用空对多3:7的比例进行配对交易,在1955年到 ...
最新文章
- shell的数字、字符串处理
- android fersco 框架,Android Fresco框架的简单使用
- ngnix mysql 缓存清除_利用Proxy Cache使Nginx对静态资源进行缓存
- 浅谈FIle协议与Http协议及区别
- 一个39岁程序员的应聘被拒
- 为什么资本主义生产的一般趋势是资本有机构成的提高?2017-12-26
- boost::core::bit_cast的测试程序
- Django中的Model模型
- TestNG如何disable一些case
- 微信封杀lol手游活动小程序?《英雄联盟手游》回应了
- 最近发现 OSChina 客户端的站内下载被广告了!!!
- HashSet底层存储元素的源码分析
- 2008 DHCP中继器代理服务
- Go语言实现md4、md5、sha256哈希算法加密
- AFTN和SITA报文简介
- 【柒】企业分析利器——强大企业模型
- 【python爬虫】http.cookiejar库之CookieJar,模拟登录与访问
- bittorrent_如何匿名和加密您的BitTorrent流量
- java获取融云token、并实现群组聊天、管理等后台接口示例
- 《RAFT-Stereo:Multilevel Recurrent Field Transforms for Stereo Matching》论文笔记