透过采购单"仓库"下拉列表框显示过程,分析"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 刷新(右键-&gt;重新查询)

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分析相关推荐

  1. Java常见异常类型及原因分析

    Java常见异常类型及原因分析 0x1 NullPointerException异常 顾名思义,NullPointerException 是空指针异常.但是在 Java 中没有指针,怎么会有 空指针异 ...

  2. 我的游戏学习日志13——类型游戏的分析(1)

    我的游戏学习日志13--类型游戏的分析(1) 1.动作游戏(ACT)的分析 Action Game,最早出现的游戏类型,衍生出如FTG.STG.FPS.SPT等不同的子类别.游戏性大都单一,一般考验玩 ...

  3. JavaScript 特有奇葩问题“字符串类型与数字类型混乱”的分析与解决,与类型转换

    字符串类型与数字类型的混乱,应该是JS最著名的奇葩问题了. 恰好最近遇到这个问题,在这里对这个问题的解决方法及产生原因进行总结与分析. Java 语言与 JavaScript 语言是什么关系.这是初学 ...

  4. linux应用日志类型,linux日志分析

    linux的日志文件可以说是最有用的了,日志文件可以让我们了解系统所处的状态,比如能查出哪些用户有登入,这也涉及相关的安全问题. 日志分析 1.了解日志文件 linux的日志文件可以说是最有用的了,日 ...

  5. 《Essential C++》笔记之传引用(pass by reference)分析

    参考博文:C++中,传值.传地址.传引用究竟有何区别 参考博文:C++作用域.局部变量.全局变量.传引用传值对比的一个例子 举例分析:把引用作为函数参数传递 bool fibon_elem(int,i ...

  6. 计算机组成原理复习要点与考题类型--选择-填空-分析-计算-简答

    目录 选择题 填空题 分析判断题 计算题 简述题 选择题 1 . 某机字长32位,其中1位表示符号位.若用定点整数表示,则最小负整数为(  ). A   -(231 -1)      B  -(230 ...

  7. 关于VB提示ByRef参数类型不符的分析

    在VB中执行过程或函数时,提示"ByRef参数类型不符" 分析问题主要由于对应参数的类型不符造成的.造成这种情况一般有几种情况: 1.传递参数未定义类型,如果参数在调用前未定义类型 ...

  8. Solidity的函数类型以及可见性分析(类比Java)

    函数类型 函数也是一种类型(值类型),它是函数的调用方式.函数类型可以被赋值吗,作为参数和返回结果.函数可以分为两类:内部函数(Internal)和外部函数(External). 内部函数Intern ...

  9. 算法交易的主要类型与策略分析

    2017-09-05 11:34 算法交易起源于上世纪中叶的配对交易 历史上最早使用算法交易的例子可以追溯到1949年.对冲基金之父阿尔弗雷德·琼斯,利用空对多3:7的比例进行配对交易,在1955年到 ...

最新文章

  1. shell的数字、字符串处理
  2. android fersco 框架,Android Fresco框架的简单使用
  3. ngnix mysql 缓存清除_利用Proxy Cache使Nginx对静态资源进行缓存
  4. 浅谈FIle协议与Http协议及区别
  5. 一个39岁程序员的应聘被拒
  6. 为什么资本主义生产的一般趋势是资本有机构成的提高?2017-12-26
  7. boost::core::bit_cast的测试程序
  8. Django中的Model模型
  9. TestNG如何disable一些case
  10. 微信封杀lol手游活动小程序?《英雄联盟手游》回应了
  11. 最近发现 OSChina 客户端的站内下载被广告了!!!
  12. HashSet底层存储元素的源码分析
  13. 2008 DHCP中继器代理服务
  14. Go语言实现md4、md5、sha256哈希算法加密
  15. AFTN和SITA报文简介
  16. 【柒】企业分析利器——强大企业模型
  17. 【python爬虫】http.cookiejar库之CookieJar,模拟登录与访问
  18. bittorrent_如何匿名和加密您的BitTorrent流量
  19. java获取融云token、并实现群组聊天、管理等后台接口示例
  20. 《RAFT-Stereo:Multilevel Recurrent Field Transforms for Stereo Matching》论文笔记

热门文章

  1. activemq高级客户端选项
  2. 基于RDP开源许可rdesktop基本介绍
  3. Android抽象布局——include、merge 、ViewStub
  4. 电脑开机老是显示explorer.exe文件损坏
  5. ios 改变图片大小缩放方法
  6. 【CCNA考试】2010-06-29-北京-987(PASS)
  7. Docker 容器技术 — docker run
  8. Linux 操作系统原理 — 文件系统 —文件
  9. 示波器DIY参考设计
  10. STM32定时器的TRGO信号