清除过滤器
文章
Louis Lu · 一月 7, 2021
本文介绍了 InterSystems 客户围绕 SDDC 和 HCI 解决方案的注意事项。
采用软件定义数据中心 (SDDC) 和超融合基础架构 (HCI) 解决方案的 InterSystems 客户需要重点关注的事项
越来越多的 IT 组织正在探究使用SDDC 和 HCI 解决方案的可行性。 这些解决方案看上去很有吸引力,其市场定位为跨异构数据中心和云基础设施可以使得 IT 管理更容易、投入的成本花费更少。 对于 IT 组织来说,潜在的好处是巨大的,许多 InterSystems 客户正在拥抱 SDDC、HCI 或两者兼有。
如果您正在考虑 SDDC 或 HCI 解决方案,请联系您的销售客户经理或销售工程师,安排与技术架构师的通话。 这对于确保成功非常重要。
这些解决方案具有高度的可配置性,组织可以从许多软件和硬件的组合中自由选择。 我们看到了我们的客户使用各种 SDDC 和 HCI 解决方案,通过这些经验,我们意识到,仔细考虑解决方案配置以避免风险是非常重要。 在某些情况下,有些客户的实施不符合关键事务型数据库系统所需的性能和弹性需求。 这导致了应用性能不佳和意外停机的出现。 如果客户的目标是为关键事务型数据库系统提供高弹性和低延迟的存储能力,则组件的选择和配置需要针对您的情况进行仔细考虑和规划,包括:
* 选择适当的组件
* 正确配置这些组件
* 使用适当的操作步骤
SDDC 和 HCI 提供了灵活性和易管理性,它们在操作系统和物理存储层之间的管理程序层内或旁路运行。 这会增加不同程度的开销。 如果配置错误,会从根本上影响磁盘延迟,这对于应用的性能而言是灾难性的。
InterSystems IRIS、Caché 和 Ensemble 的设计注意事项
以下最低要求和设计注意事项列表基于我们对 SDDC 和 HCI 解决方案的内部测试。 请注意,这不是一个参考架构,意味着您的应用需求将根据您的实际情况和性能目标有所更改。
网络
* 每节点拥有两个或更多的 10Gb NIC 接口,专门用于存储流量。
* 本地两台无阻塞速率 10Gb 交换机,实现交换机的弹性连接。
* 当然也可以选择 25、40、50 或 100Gb 而不是 10Gb速率,将其作为对 HCI 的前瞻性投资,以满足特定基准和测量应用程序的要求。
**计算**
* 至少一个六节点群集,以便在维护和故障期间提供更高的弹性和可预测的性能。
* 英特尔可扩展 Gold 或 Platinum 处理器或更高版本,2.2Ghz 或更高主频。
* 以每个 CPU 插槽 6 个 DDR4-2666 DIMM 为一组的形式安装 RAM(最少 384GB)。
存储
* 全闪存存储。 这是唯一推荐的存储选项。 InterSystems 强烈建议不要将混合或分层 HCI 存储用于生产工作负载。
* 每个物理节点至少两个磁盘组。 每个磁盘组应支持至少三个大容量驱动器。
* 独占使用写入密集型 12Gbps SAS SSD 或 NVMe SSD。
* 对于具有缓存和容量层的全闪存解决方案,建议将 NVMe 用于缓存层,将写入密集型 12Gbps SAS 用于容量层。
* 对 Linux 虚拟机使用 LVM PE 条带化,从而将 IO 分布在多个磁盘组(请联系 InterSystems 获得指南)。
* 对于 Linux 虚拟机上的所有数据库和写入映像日志 (WIJ) 文件使用异步 IO 及 rtkaio 库。 这样可以绕过文件系统缓存并降低写入延迟(请参见[文档](http://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls)或与 WRC 联系以获取有关在 Linux 上正确启用异步 IO 的帮助)。
这些最低要求建议已证明可以减轻 SDDC 和 HCI 的开销,但并不确保应用性能。 与任何新技术一样,测试您自己的应用的性能和弹性对于任何成功部署都是至关重要的。
重申一次,如果您正在考虑 SDDC 或 HCI 解决方案,请联系您的销售客户经理或销售工程师,他们会为你安排与技术架构师的通话。这对于确保成功至关重要。
文章
Lilian Huang · 八月 1, 2023
VR ICU® 是 InterSystems FHIR 创新孵化器 Caelestinus 的参与者。这篇文章将向您介绍我们利用 InterSystems FHIR Server 为医疗保健提供的 VR 解决方案。
我们是一家技术初创企业虚拟实验室,利用先进的 VR/AR 技术开发解决方案。VR ICU® 是一个针对重症监护室医务人员的培训平台,是在 Covid 时代为满足医院需求而创建的。
与InterSystems合作的优势
我们的 VR ICU® 解决方案符合实践需求,是与医院合作开发的。
除了技术解决方案和技能学习本身,记录培训课程、培训进度和成功率对于医院或麻醉学和重症监护部门的有效管理也至关重要。医务长可以通过了解谁在何时接受了培训,清楚地掌握能够在重症监护室使用设备的人员数量,从而有效地对他们进行培训,以保持技能、有控制地规划人员技能储备并提高他们的能力。
在这方面,与 InterSystems 的合作对我们来说至关重要,它使我们能够在应用程序中存储每次培训期间的数据。目前,我们会记录参与者的姓名、培训日期和时长、培训类型、设备类型、错误数量和类型,必要时还会记录培训成功完成的信息。
如何使用?用户登录应用程序并选择一个账户。
根据 HL7 标准,该账户作为从业人员存在于数据库的资源下。培训课程开始时,会在应用程序中创建一个新的 "任务"--在这里输入培训课程的开始时间和培训课程的类型,课程结束时,再次输入培训课程的结束时间。错误会写入输出表。培训完成后,任务中的数据将序列化为 JSON 格式,并使用 FHIR API 发送到云端。为了使 VR 应用程序之外的数据可视化,我们开发了一款平板电脑应用程序。该应用程序与存储在云端的数据相连,并显示特定用户的个人训练课程。
人力资源部门通过培训数据了解受训人员完成培训的总体情况和水平,从而有效地规划他们的进一步培训,并跟踪了解员工的能力及其在重症监护室护理过程中的替换性。您可以点击这里:https://www.youtube.com/watch?v=3oO0uuHy0kg&t=8s
如今,医院、大学和模拟中心都在使用 VR ICU®。
虚拟现实技术将教育和培训提升到了一个新的水平。通过体验学习,可以提高培训效果和记忆力。
在 VR ICU® 中使用 InterSystems 的 FHIR 云服务器作为存储培训进度数据的工具,并使用 FHIR API 进行通信,这也对我们进军国外市场产生了积极影响,尤其是在德国,FHIR 标准是一种广为接受的解决方案,用于与人力资源部门传输信息,并与第三方调度系统进行通信。
麻醉学和重症监护审查参考:https://www.youtube.com/embed/Qve5xEm89cU?feature=oembed
它是如何开始的?
2020 年,一场大流行病袭击了我国。医院人满为患,人手短缺,尤其是重症监护室。麻醉、复苏和重症医学科主任在晚间新闻中解释说,如果更多的医生被隔离或生病,他就没有足够的合格人员来操作肺部呼吸机。其他医院也证实了同样的情况。我们萌生了制作一个专门用于培训的肺部呼吸机数字拷贝,帮助医院培训其他科室医生的想法。
我们找到了麻醉复苏部(ARO)的负责人、模拟中心的专家。医生们支持我们的想法,有些人还参与了开发工作。我们还得到了医疗设备制造商的支持,他们看到了虚拟现实培训的附加值。
我们是如何开展项目的,解决方案的重要性何在?
1. 我们评估了重症监护室的现状:
- 在没有真实病人和/或医疗设备的情况下,50% 以上的重症监护室程序无法进行培训。
- 医疗设备制造商难以将医务人员集中到一处进行培训(只有 30% 的受训人员能坚持到培训结束)
- 过去两年中,麻醉学和重症监护部门的人员流动率约为 20%。
2. 问题的解决方案:
- 虚拟现实自动培训平台
- 模拟重症监护室的手术过程,无需真实病人,也无需使用真实医疗设备
- 节省技术和医疗用品
- 也可用于远程培训,从不同地点/工作场所进入同一个虚拟空间
- 在安全的环境中进行风险情况演练
- 将人为错误的风险降至最低
3. 潜力:
- 利用人工智能(AI)模拟和练习危急情况,确定正确的程序
- 人工智能可模拟病人-设备-病人之间的互动
- 制造商的设备集中在一个虚拟空间,使医院的培训更加容易
愿景
VR ICU® 的目标是作为一个平台,让医院从实际使用的设备目录中选择 3D 设备,并从中创建培训环境。
我们向医疗设备制造商提出的愿景最初得到了 BBraun、费森尤斯和 Linet 的支持。随后,其他公司也纷纷效仿这些大胆的先行者。我们还根据所进入的市场扩大我们的设备组合。目前,我们在美国、亚洲和南美都有合作伙伴,他们正在补充信息并与制造商进行谈判。
我们正在全球会议上展示 VR ICU®,我们很高兴能成为 Caelestinus 孵化器的一部分。由于我们与 InterSystems 的合作,我们有机会参加在西雅图举行的 InterSystems 2022 年全球峰会,现在我们正在拉斯维加斯参加 HLTH 2022。
VR ICU® 已经赢得了许多奖项,最近在奥地利林茨,我们凭借该解决方案赢得了最佳初创企业奖。
这些成功的展示吸引了投资者的关注。我们欢迎那些希望进一步开发我们产品的人向我们推荐他们。我们计划在 2023 年向捷克、斯洛伐克和德国的医院出售许可证。我们欢迎商业合作伙伴以及能够加快 VR ICU® 实际应用--市场进入进程或希望为人工智能/VR 版本的开发做出贡献的合作伙伴。
原文来自这里:https://community.intersystems.com/node/529381
文章
Frank Ma · 六月 27, 2022
比较不同的商业智能技术是非常有趣的。我很好奇它们在功能、开发工具、速度和可用性方面有什么不同。
在这个应用程序中,我选择了一个有欧洲各国水状况的数据集。这是一个开源的数据集,包含1991年到2017年的观测数据。
团队和我决定使用IRIS BI、Tableau、PowerBI和InterSystems Reports(由Logi Reports驱动)在这个BI数据集的基础上制作一个模型
对于前端,我们通过Embedded Python在PythonFlask中制作了一个网页界面。
顺便说一下,其结果可以在这个网页上看到:http://atscale.teccod.com:8080/ 你可以看看demo stand (演示台),因为从资源库部署一个容器可能需要多至20分钟的时间。大量的python包,后面会有更多的原因。
主页面
数据
事实上,数据似乎很小,期间只有17年 :)
因此,在现有的基础上,我想延续数据集,为此使用了一个神经网络。使用同样的嵌入式Python,使用了Tensorflow,这个包下载后占据了511MB,不要惊讶
实际上,这也是容器部署时间长的原因--为神经网络下载了很多包,相当多的相关包,安装时间很长。不过会有一篇关于神经网络和Integrated ML(一体化机器学习)的单独文章,我很快会发表。
我还要说的是,预测的结果被输入到同一个数据库,所以你可以通过BI工具看到数据集。但是预测只针对法国的一条河,请仔细看一下。因为我们只有足够的力量计算一件事。完整的预测会花很长的时间。
数据立方体
数据立方体是在IRIS中制作的,同时立方体也是在Adaptive Analytics(由AtScale驱动)中制作的。因此,IRIS的BI仪表盘是在IRIS上建立的,其余的工具(Logi、PowerBI、Tableau)从AtScale上获取数据。
仪表板
实际上商业智能系统是以多种形式呈现的。
这是在python中的Dash。
我们喜欢的IRIS BI
InterSystems报告(由Logi报告提供)。
PowerBI
Tableau 样例
完成
对于所介绍的所有BI系统,源文件都可以在资源库中找到。你可以看到报告和仪表盘是如何工作的,并在你未来的项目中使用它们。
通过它们,你可以直观地看到一个特定的系统是如何工作的,也可以了解一个特定的系统有哪些开发工具。
我们没时间来制作一个页面,让你可以输入各种参数和条件,使用神经网络的可能值进行计算。这里有一些先决条件,有一个实施神经网络的例子,以及在其帮助下所做的预测,这些都是在嵌入式Python中实现的。神经网络已被训练,启动脚本也是可用的,位于 https://github.com/teccod/water-conditions-Europe/blob/main/iris/src/PythonFlask/pages/ml/ml_run.py文件夹中。
谢谢你阅读这篇文章,我在等待评论和反馈。很快就会有一篇关于在嵌入式Python和IntegratedML(一体化机器学习)中比较神经网络的文章,我将把它附在这篇文章中。
问题
Weiwei Yang · 一月 25, 2021
生产环境要使用80端口访问服务器,采用直接部署程序的方式,是在Linux服务器上同时部署HealthConnect和Apache。类似的现在想要使用Docker技术,在一台服务器上部署了HealthConnect和Apache容器,该如何配置http.conf文件,使80端口的请求转到HealthConnect上呢?如果这种方式不可行,有没有其他方法呢? 你好,
请参考在Openexchange中发布的例子:Example of InterSystems IRIS with external Apache and WebGateway( https://openexchange.intersystems.com/package/iris-webgateway-example)
问题
Wang li · 三月 30, 2021
大家好,我想咨询下如何实现用HealthShare开发socket的接口,例如开发socket对外的BS,以及socket调用的BO 您好,InterSystem的产品家族都支持直接使用Socket,借助UDP或TCPIP与第三方通信,参考
TCP:https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=GIOD_tcp
UDP:https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=GIOD_udp
如果是使用BS或者BO的话,则可以使用IRIS提供的多种适配器按需开发获得,参考
https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=PAGE_interop_protocols 好的,谢谢
文章
姚 鑫 · 七月 8, 2021
# 第三十一章 检查命名空间和类
类`%XML.Namespaces`提供了两个类方法,可用于检查XML命名空间及其包含的类:
## GetNextClass()
```java
classmethod GetNextClass(namespace As %String,
class As %String) as %String
```
返回给定`XML`命名空间中给定类之后的下一个类(按字母顺序)。当没有更多的类时,此方法返回`NULL`。
## GetNextNamespace()
```java
classmethod GetNextNamespace(namespace As %String) as %String
```
返回给定命名空间之后的下一个命名空间(按字母顺序)。当没有更多的命名空间时,此方法返回`NULL`。
在这两种情况下,只考虑当前的InterSystems IRIS命名空间。此外,映射的类也会被忽略。
例如,以下方法列出当前InterSystems IRIS命名空间的XML命名空间及其类:
```java
ClassMethod WriteNamespacesAndClasses()
{
Set ns=""
Set ns=##class(%XML.Namespaces).GetNextNamespace(ns)
While ns '=""
{
Write !, "The namespace ",ns, " contains these classes:"
Set cls=""
Set cls=##class(%XML.Namespaces).GetNextClass(ns,cls)
While cls '=""
{
Write !, " ",cls
Set cls=##class(%XML.Namespaces).GetNextClass(ns,cls)
}
Set ns=##class(%XML.Namespaces).GetNextNamespace(ns)
}
}
```
在终端中执行时,此方法会生成如下所示的输出:
```java
The namespace http://www.address.org contains these classes:
ElRef.NS.Address
GXML.AddressNS
MyApp4.Obj.Address
MyAppNS.AddressNS
Obj.Attr.Address
Obj.Ns.Address
Obj.Ns.AddressClass
The namespace http://www.doctor.com contains these classes:
GXML.DoctorNS
The namespace http://www.one.org contains these classes:
GXML.AddressNSOne
GXML.DoctorNSOne
GXML.PersonNSOne
...
```
文章
姚 鑫 · 一月 18, 2023
# 第四十九章 使用 ^SystemPerformance 监视性能 - 复制配置文件
# 复制配置文件
可以使用以下 `API` 命令将现有配置文件复制到具有不同名称的文件:
```java
set rc=$$copyprofile^SystemPerformance("sourceprofilename","targetprofilename")
```
必须指定:
- `sourceprofilename` - 现有配置文件的名称
- `targetprofilename` - 要创建的配置文件的名称。这必须用双引号引起来。
如果成功,该函数返回 `1`。如果不成功,它返回一个 `0` 后跟一个 `carat` 和任何错误的原因。
其中 `sourceprofilename` 是现有配置文件的名称,`targetprofilename` 必须是唯一的并且不能包含空格或空白字符。
例如,要复制 `2minrun` 配置文件,请输入以下内容:
```java
set rc=$$copyprofile^SystemPerformance("2minrun","5minrun")
```
下次运行 `^SystemPerformance` 实用程序时,配置文件列表包括以下配置文件名称和说明:
```java
2minrun A 2-minute run sampling every 30 seconds
5minrun A 2-minute run sampling every 30 seconds
```
现在可以按照本指南这一部分的编辑配置文件中的说明编辑新配置文件。
# 删除配置文件
可以使用以下 `API` 命令删除现有配置文件(预定义的“测试”配置文件除外):
```java
set rc=$$delprofile^SystemPerformance("profilename")
```
- `profilename` - 要删除的配置文件的名称。这必须用双引号引起来。
如果成功,该函数返回 `1`。如果不成功,它返回一个 `0` 后跟一个 `carat` 和任何错误的原因。
例如,要删除 `2minrun` 配置文件,请输入以下内容:
```java
set rc=$$delprofile^SystemPerformance("2minrun")
```
下次运行 `^SystemPerformance` 实用程序时,配置文件列表不包括 `2minrun` 配置文件。
# ^SystemPerformance Utility 创建的性能报告
`^SystemPerformance` 实用程序生成特定于平台的报告,如本章所述。该报告分为几个部分,如下面的清单所示:
```java
Configuration
IRISTEST3 on machine testsystem
Customer: InterSystems Development
License : 123456
InterSystems IRIS Version String: InterSystems IRIS for Windows (x86-32) 2018.1 (Build 508) Fri Jan 26 2018 17:51:22 EDT
--------------------------------------------------------------
Profile
Profile run "test" started at 10:07 on Jun 01 2016.
Run over 10 intervals of 30 seconds.
--------------------------------------------------------------
license
Product=Enterprise
License Type=Concurrent User
Server=Multi
Platform=Heterogeneous
Licensed Users=1000
Licensed CPUs=16
.
.
.
--------------------------------------------------------------
End of InterSystems IRIS Performance Data Report
```
本节中的表格描述了每个特定于平台的报告的部分。这些部分在每个表中按字母顺序列出,以帮助您更轻松地找到特定部分。仅收集一次的数据标有星号 (`*`)。其余数据是在整个配置文件运行过程中收集的。
注意:在以下所有表格中,标有 `*` 的数据每次运行收集一次。
文章
Jingwei Wang · 三月 24, 2022
REST是一种架构风格,而不是一种格式。尽管REST经常使用HTTP来传输消息,使用JSON来传递数据,但你也可以用XML或纯文本来传递数据。REST利用了现有的网络标准,如HTTP、URL、XML和JSON。
虽然它可以使用XML来描述数据,但它更常使用JSON,这是一个轻量级的数据封装器。
InterSystems REST服务
InterSystems REST服务由以下组件组成:
规范类(%REST.Spec的一个子类):这个类包含了REST服务的OpenAPI 2.0规范(Swagger)。InterSystems支持几个扩展属性,你可以在规范中使用。
调度类(%CSP.REST的一个子类):这个类负责接收HTTP请求并在实现类中调用合适的方法。
实现类(%REST.Impl的子类):这个类定义了实现REST调用的方法。
Web应用程序:它通过InterSystems Web Gateway提供对REST服务的访问。
使用API 管理工具创建REST服务 - 基于 OpenAPI 2.0规范
/api/mgmnt/
可以使用/api/mgmnt服务来创建、更新和删除REST服务。
使用/api/mgmnt创建 .disp .impl 和 .spec 类
使用http://localhost:52773/api/mgmnt/v2/namespace/myapp
注意: 命名空间必须已经存在,myapp可以自己定义,使用POST。
生成成功消息:
{
"msg": "New application myapp created"
}
创建Web应用程序 名字:/csp/namespace 分派类:myapp.disp 应用角色: %DB_%DEFAULT
补全实现类中的方法
使用^%REST Routine创建REST服务 - 基于 OpenAPI 2.0规范
do ^%REST
使用%REST.API类创建REST服务 - 基于 OpenAPI 2.0规范
可以用它来发现服务器上的REST服务,为这些REST服务生成OpenAPI 2.0规范,并在服务器上创建、更新、或删除REST服务。
使用%REST.API 创建 .disp .impl 和 .spec 类
set file="c:/temp/swagger.json"
set obj = ##class(%DynamicAbstractObject).%FromJSON(file)
do ##class(%REST.API).CreateApplication("petstore",.obj,,.new,.error)
//examine error and decide how to proceed...
...
创建Web应用程序
名字:/csp/namespace
分派类:myapp.disp
应用角色: %DB_%DEFAULT
补全实现类中的方法
基于%CSP.REST 手动创建REST 服务 - 不需要定义OpenAPI 2.0规范
创建REST 分派类,继承 %CSP.REST 类
定义URL map
Class REST.Interface.RestHandler Extends %CSP.REST
{
Parameter CONTENTTYPE = "application/json";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CHARSET = "utf-8";
XData UrlMap
{
<Routes>
<Map Prefix="/coffee/sales" Forward="MyLib.coffee.SalesREST"/>
<Map Prefix="/coffee/repairs" Forward="MyLib.coffee.RepairsREST"/>
<Map Prefix="/coffee" Forward="MyLib.coffee.MiscREST"/>
</Routes>
}
}
创建REST 服务类,继承 %CSP.REST 类
REST 服务类URL map 定义,例如MyLib.coffee.SalesREST类中URL map定义REST 服务类
Class MyLib.coffee.SalesREST Extends %CSP.REST
{
Parameter HandleCorsRequest = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/request" Method="GET" Call="Request" />
<Route Url="/request" Method="POST" Call="Request" />
</Routes>
}
/// 根据文档号,输出其HTML格式
/// pDocNo:文档编号
ClassMethod Request() As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Try
{
Set tSC = ##class(REST.Util).GetSales(pName)
W tSC
}
Catch (e)
{
Set tSC=e.AsStatus()
}
Return tSC
}
}
创建Web应用程序
名字:/csp/namespace 或其他名字 分派类:REST.Interface.RestHandler 应用角色: %DB_%DEFAULT
文章
Jingwei Wang · 七月 25, 2022
本章介绍了使用InterSystems IRIS作为企业服务总线,描述了InterSystems IRIS ESB架构,并提供了部署ESB的概述。
企业服务总线的概念
企业服务总线(ESB)提供了一个单点来访问和管理具有SOAP、REST或其他网络API的应用程序。ESB提供了以下功能。
提供一个中心来发现和访问服务。
将应用程序与服务隔离开来,允许你在一个地方改变服务的描述,而不需要更新所有依赖它的应用程序。例如,你可以改变服务器的地址,甚至服务的API,并在ESB中处理这些变化。这为你的应用程序提供了协议独立性。如果一个应用程序是使用SOAP API开发的,但一个新的服务用REST API提供了额外的功能,ESB可以使新的REST服务作为REST和SOAP API可用,允许你添加新服务的功能,同时保持对现有应用程序的兼容性。
提供一种机制来组织和跟踪企业使用的应用程序以及这些应用程序之间的依赖关系。。
ESB架构
InterSystems IRIS ESB架构有以下组成部分。
将传入的请求与服务器连接起来的路由机制。这是由具有专门业务服务(BS)和业务操作(BO)的 production实现的,也可以选择业务流程(BP)。
公共服务注册中心--这个服务注册中心可以通过ESB公共REST API被ESB客户访问。开发人员使用它来获取有关通过 ESB 可用的服务的信息。
外部服务注册中心--这个服务注册中心只能在ESB production中访问。它向ESB业务主机提供端点信息。
SAML令牌验证服务。
ESB production和服务注册处都应该被定义在一个专门用于ESB的命名空间中。
注意:InterSystems建议在一个InterSystems IRIS实例上只运行一个ESB production。
在其最简单的形式中,ESB由透传服务、透传操作和服务注册表组成。下面说明了一个简单的ESB的架构。
通常,应用程序开发人员使用网页或应用程序来查询 ESB 服务注册表,以了解可用的服务并获得提供对底层服务的访问的透传业务服务的 URL。这个查询和服务发现过程是在开发者创建客户端应用程序时进行的。一旦开发者拥有了访问服务所需的URL、文档和其它信息,客户端应用程序就不需要为了调用服务而访问服务注册表。在某些环境中,客户端应用程序可能会对公共API进行运行时调用,以确保注册表项在上次访问后没有被修改。
客户机应用程序调用透传服务。透传服务将消息发送到在其目标设置中指定的透传操作。透传操作被配置为在外部服务注册表中查找端点URL。然后,它使用该端点URL调用外部服务。外部服务将响应返回给透传操作,后者将响应指向透传服务。透传服务反过来将响应返回给客户端应用程序。
除了透传服务和操作外,你还可以定义更复杂的服务、操作和业务流程,以增加一些功能,例如,根据呼叫的内容,将呼叫从一个传入的服务路由到多个外部服务。这允许ESB提供一个单一外部服务所不能提供的服务。客户端应用程序与实现扩展服务所需的外部服务隔绝。
修改用于服务的参数或协议。如果一组应用程序是使用一种服务开发的,但后来有了具有不同 API 的高级服务,与其修改每个应用程序,不如在 ESB 中进行转换。客户端应用程序与从一个外部服务转换到另一个服务所需的变化隔绝。直接在ESB上实现服务。如果没有符合需求的外部服务,可以使用ObjectScript在ESB上实现一个。
但是,将这些更复杂的服务添加到 ESB 上有一个效率成本。这些复杂服务的额外处理成本减缓了ESB处理请求的时间,降低了吞吐量。对于需要非常高吞吐量的ESB系统,你可以通过消除持久化消息来减少处理请求的开销。持久性消息是指从透传服务发送到透传操作的对象,以及由操作返回给服务的对象。这些对象被存储在InterSystems IRIS数据库中。这些持久性的消息在跟踪和报告ESB处理的调用以及排除任何问题时非常有用。但创建这些对象需要资源,对于吞吐量非常高的系统,这些对象所需的存储量可能非常大。为了维护系统,你必须经常清除这些信息。你可以抑制对持久化消息的使用,以获得效率,但代价是降低灵活性。更多信息请参见 "在通过式服务和操作中抑制持久化消息"。
注意:如果你正在运行HealthShare产品,HealthShare服务注册表与InterSystems IRIS服务注册表不同。HealthShare服务注册表提供了与InterSystems IRIS外部服务注册表类似的功能。在大多数情况下,你应该继续使用HealthShare服务注册表,而不是使用InterSystems IRIS外部服务注册表。
配置ESB
下面包含安装和配置InterSystems IRIS的几个配置程序:
创建一个具有互操作性的命名空间,以包含ESB production和服务注册。
配置Web网关。
创建外部服务注册表条目,定义ESB所使用的外部服务的端点。
创建 ESB production,添加提供服务的业务服务和业务操作,并启动该 production。
创建通过管理门户和公共 REST API 访问公共服务注册中心所需的角色和用户。
创建将业务服务提供给客户所需的Web应用程序。
创建公共服务注册表条目,描述通过ESB访问的服务。
文章
姚 鑫 · 一月 22, 2022
# 第三十一章 SQL函数 CONVERT
将给定表达式转换为指定数据类型的函数。
```java
CONVERT(datatype,expression[,format-code])
{fn CONVERT(expression,datatype)}
```
# 参数
- `expression` - 要转换的表达式。
- `datatype` - 要将表达式转换为的数据类型。
- `format` - 可选-指定日期和时间格式的整数代码,用于在日期/时间/时间戳数据类型和字符数据类型之间进行转换。
此参数仅用于通用标量语法形式。
# 描述
这里描述了`CONVERT`函数的两种不同实现。
两者都将一种数据类型中的表达式转换为另一种数据类型中的相应值。
两者都执行日期和时间转换。
注意:这两个`CONVERT`实现中的参数以不同的顺序表示。
第一个是与MS SQL Server兼容的通用 IRIS标量函数,它接受三个参数。
第二个是带有两个参数的 ODBC标量函数。
下面的文本将分别处理这两种形式的`CONVERT`。
- `CONVERT(datatype,expression)`支持流数据的转换。
例如,可以将字符流字段的内容转换为数据类型为`VARCHAR`的字符串。
- `{fn CONVERT(expression,datatype)}`不支持流数据的转换;
指定要表达的流字段将导致`SQLCODE -37`错误。
为两个版本的`CONVERT`指定一个无效值将导致`SQLCODE -141`。
如果表达式没有定义的数据类型(例如ObjectScript提供的主机变量),则其数据类型默认为字符串数据类型。
# CONVERT(datatype,expression,format-code)
可以通过执行`VARCHAR-to-VARCHAR`转换来截断字符串,指定输出字符串长度小于表达式字符串长度。
在使用`CONVERT`(或`CAST`)时,如果字符数据类型(如`CHAR`或`VARCHAR`)没有指定长度,则默认的最大长度为`30`个字符。
如果二进制数据类型(如`binary`或`VARBINARY`)没有指定长度,则默认的最大长度为`30`个字符。
否则,这些没有指定长度的数据类型将被映射到一个`1`个字符的`MAXLEN`,如`data types`表所示。
可以执行`BIT`数据类型转换。
允许的值为`1`、`0`或`NULL`。
如果指定任何其他值,IRIS将发出`SQLCODE -141`错误。
在下面的嵌入式SQL示例中,两者都是一个`NULL`的`BIT`转换:
```java
ClassMethod Convert()
{
s a=""
&sql(
SELECT CONVERT(BIT,:a),
CONVERT(BIT,NULL)
INTO :x,:y)
w !,"SQLCODE=",SQLCODE
w !,"the host variable is:",x
w !,"the NULL keyword is:",y
}
```
可选的`format-code`参数指定日期、`datetime`或时间格式。
该格式既可用于定义从日期/时间/时间戳数据类型转换为字符串时的输出,也可用于定义从字符串转换为日期/时间/时间戳数据类型时的输入。
支持以下格式代码;
输出两位数年份的格式代码列在第一列;
输出四位数年或不输出年的格式列在第二列:
Two-digit year codes| Four-digit year codes| Format
---|---|---
|0 or 100 |Mon dd yyyy hh:mmAM (or PM)
1| 101 |mm/dd/yy
2| 102 |yy.dd.mm
3| 103 |dd/mm/yy
4| 104 |dd.mm.yy
5| 105 |dd-mm-yy
6| 106 |dd Mon yy
7| 107 |Mon dd, yy (no leading zero when dd < 10)
| 8 or 108| hh:mm:ss
| 9 or 109| Mon dd yyyy hh:mm:ss:nnnAM (or PM)
10| 110 |mm-dd-yy
11| 111 |yy.mm.dd
12| 112 |yymmdd
|13 or 113| dd Mon yyyy hh:mm:ss:nnn (24 hour)
|14 or 114| hh:mm:ss.nnn (24 hour)
|20 or 120| yyyy-mm-dd hh:mm:ss (24 hour)
|21 or 121| yyyy-mm-dd hh:mm:ss.nnnn (24 hour)
|126| yyyy-mm-ddThh:mm:ss,nnnn (24 hour)
|130| dd Mon yyyy hh:mm:ss:nnnAM (or PM)
|131| dd/mm/yyyy hh:mm:ss:nnnAM (or PM)
以下是日期和时间转换的特性:
- 取值范围:允许的日期范围为`0001-01-01 ~ 9999-12-31`。
- 默认值:
- 将时间值转换为`TIMESTAMP`、`POSIXTIME`、`DATETIME`或`SMALLDATETIME`时,日期默认为`1900-01-01`。
注意,对于`{fn CONVERT()}`,日期默认为`1841-01-01`。
- 将日期值转换为`TIMESTAMP`、`POSIXTIME`、`DATETIME`或`SMALLDATETIME`时,时间默认为`00:00:00`。
- `Default Format`:如果没有指定`Format -code`, `CONVERT`将尝试从指定的值确定格式。
如果不能,则默认为格式代码`100`。
- 两位数年份:从00到49的两位数年份转换为21世纪的日期(2000到2049);
从50到99的两位数年份转换为20世纪的日期(1950到1999)。
- 分数秒:分数秒前可以加句号(`.`)或冒号(`:`)。
这些符号有不同的含义:
- 句点是默认值,可用于所有格式代码。
句号表示标准分数;
因此,`12:00:00.4`表示十分之四秒,而`12:00:00.004`表示千分之四秒。
分数精度的位数没有限制。
- 冒号只能用于以下格式代码值:`9/109`、`13/113`、`14/114`、`130和131`。
冒号表示后面的数字是千分之一秒;
因此`12:00:00:4`表示四万分之一秒(`12:00:00.004`)。
冒号后面的数字限制为3位。
当指定表达式的格式无效或格式与格式代码不匹配时,将产生`SQLCODE -141`错误。
指定一个不存在的格式代码将返回`1900-01-01 00:00:00`。
# {fn CONVERT(expression,datatype)}
这是ODBC标量函数。
它支持以下ODBC显式数据类型转换。
必须使用“SQL_”关键字指定这种形式的`CONVERT`的数据类型转换。
在下表中,有两组转换数据类型,第一组转换数据值和数据类型,第二组转换数据类型,但不转换数据值:
Source | Conversion
---|---
Any numeric data type| SQL_VARCHAR, SQL_DOUBLE, SQL_DATE, SQL_TIME
%String |SQL_DATE, SQL_TIME, SQL_TIMESTAMP
%Date| SQL_VARCHAR, SQL_POSIXTIME, SQL_TIMESTAMPSQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT, SQL_DATE
%Time| SQL_VARCHAR, SQL_POSIXTIME, SQL_TIMESTAMP SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT,SQL_SMALLINT, SQL_TINYINT, SQL_TIME
%PosixTime| SQL_TIMESTAMP, SQL_DATE, SQL_TIME SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
%TimeStamp |SQL_POSIXTIME, SQL_DATE, SQL_TIME SQL_VARCHAR, SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
Any non-stream data type| SQL_INTEGER, SQL_BIGINT, SQL_SMALLINT, SQL_TINYINT
Any non-stream data type| SQL_DOUBLE
`SQL_VARCHAR`是标准的ODBC表示。
在转换为`SQL_VARCHAR`时,日期和时间被转换为相应的ODBC表示;
数字数据类型值转换为字符串表示。
从`SQL_VARCHAR`转换时,该值必须是有效的ODBC `Time`、`Timestamp`或`Date`表示。
- 当将时间值转换为`SQL_TIMESTAMP`或`SQL_POSIXTIME`时,未指定的日期默认为`1841-01-01`。
注意,对于`CONVERT()`,日期默认为`1900-01-01`。
- 将`date`值转换为`SQL_TIMESTAMP`或`SQL_POSIXTIME`时,时间默认为`00:00:00`。
在这种语法形式中,小数秒前面可以加句号(`.`)或冒号(`:`)。
这些符号有不同的含义。
句号表示标准分数;
因此,`12:00:00.4`表示十分之四秒,而`12:00:00.004`表示千分之四秒。
冒号表示接下来的是千分之一秒;
因此`12:00:00:4`表示千分之四秒。
冒号后面的数字限制为3位。
在转换为整数数据类型或`SQL_DOUBLE`数据类型时,数据值(包括日期和时间)将转换为数字表示。
对于`SQL_DATE`,这是自1841年1月1日以来的天数。
对于`SQL_TIME`,这是自午夜以来的秒数。
当遇到非数字字符时,输入字符串将被截断。
整数数据类型还截断十进制数字,返回数字的整数部分。
`{fn CONVERT(expression,datatype)}`不支持流数据的转换;
指定要表达的流字段将导致`SQLCODE -37`错误。
转换成任何数据类型的`NULL`仍然是`NULL`。
空字符串(`"`),或任何非数字字符串值转换如下:
- `SQL_VARCHAR`和`SQL_TIMESTAMP`返回提供的值。
- 数字数据类型转换为`0`(零)。
- `SQL_DATE`和`SQL_TIME`转换为`NULL`。
# CONVERT 类方法
还可以使用`CONVERT()`方法调用执行数据类型转换,使用" `SQL_ `"关键字指定数据类型:
```java
$SYSTEM.SQL.Functions.CONVERT(expression,convert-to-type,convert-from-type)
```
如下示例所示:
```java
WRITE $SYSTEM.SQL.CONVERT(60945,"SQL_VARCHAR","SQL_DATE")
2007-11-11
```
# 示例
## CONVERT() 示例
下面的示例使用标量语法形式的`CONVERT`。
下面的示例比较了使用`DECIMAL`和`DOUBLE`数据类型对小数的转换:
```sql
SELECT CONVERT(DECIMAL,-123456789.0000123456789) AS DecimalVal,
CONVERT(DOUBLE,-123456789.0000123456789) AS DoubleVal
```
下面的示例将字符流字段转换为`VARCHAR`文本字符串。
它还使用`CHAR_LENGTH`显示字符流字段的长度:
```sql
SELECT Notes,CONVERT(VARCHAR(80),Notes) AS NoteText,CHAR_LENGTH(Notes) AS TextLen
FROM Sample.Employee WHERE Notes IS NOT NULL
```
下面的例子展示了几种将出生日期字段(`DOB`)转换为格式化字符串的方法:
```sql
SELECT DOB,
CONVERT(VARCHAR(20),DOB) AS DOBDefault,
CONVERT(VARCHAR(20),DOB,100) AS DOB100,
CONVERT(VARCHAR(20),DOB,107) AS DOB107,
CONVERT(VARCHAR(20),DOB,114) AS DOB114,
CONVERT(VARCHAR(20),DOB,126) AS DOB126
FROM Sample.Person
```
默认格式和代码`100`格式是相同的。
因为`DOB`字段不包含时间值,所以显示时间的格式(这里包括默认值`10`0、`114`和`126`)提供一个零值,它表示`12:00AM`(午夜)。
代码`126`格式提供了一个不包含空格的日期和时间字符串。
## {fn CONVERT()} 示例
下面的示例使用了`ODBC`语法形式的`CONVERT`。
下面的嵌入式SQL示例将混合字符串转换为整数。
IRIS在第一个非数字字符处截断字符串,然后将结果数字转换为规范形式:
```java
ClassMethod Convert1()
{
s a="007 James Bond"
&sql(SELECT {fn CONVERT(:a, SQL_INTEGER)} INTO :x)
w !,"SQLCODE=",SQLCODE
w !,"the host variable is:",x
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQLCommand).Convert1()
SQLCODE=0
the host variable is:7
```
下面的示例将`“DOB”`(出生日期)列中的日期转换为`SQL_TIMESTAMP`数据类型。
```sql
SELECT DOB,{fn CONVERT(DOB,SQL_TIMESTAMP)} AS DOBtoTstamp
FROM Sample.Person
```
生成的时间戳格式为`“yyyy-mm-dd hh:mm:ss”`。
下面的示例将`“DOB”`(出生日期)列中的日期转换为`SQL_INTEGER`数据类型。
```sql
SELECT DOB,{fn CONVERT(DOB,SQL_INTEGER)} AS DOBtoInt
FROM Sample.Person
```
下面的示例将`“DOB”`(出生日期)列中的日期转换为`SQL_VARCHAR`数据类型。
```sql
SELECT DOB,{fn CONVERT(DOB,SQL_VARCHAR)} AS DOBtoVChar
FROM Sample.Person
```
生成的字符串格式为:`yyyy-mm-dd`。
公告
Claire Zheng · 一月 23, 2022
亲爱的社区开发者们,
我很高兴地向大家介绍一位我们的新版主@黎卫东(Weidong Li)。
@黎卫东(Weidong Li)目前担任上海嘉会国际医院集成平台经理一职
以下是@黎卫东(Weidong Li)的一些自我介绍:
– 我从加入嘉会之后开始了解 InterSystems 的技术以及集成平台开发。接触并使用了 InterSystems早期的Caché版本,Cube, Ensemble 并升级到了基于 Iris 的 Health Connect 平台,并深度了解这些版本的一些特性以及基于 Health Connect 打造高效的集成平台。
– 本人有超过16年的医疗信息化经验,熟悉 IHE/DICOM/HL V2/V3,有着丰富的领域知识。曾先后就职于 INFINITT,AGFA, Carestream 等主流的 HIT 公司,设计并开发过多种医疗信息系统及设计的信息集成。在目前医院,带领一个小型的团队,基于 Health Connect,从0开始设计了整个集成平台的底层架构,整体业务流程,开发流程,开发规范,发布部署规范,第三方系统接入,运维部署,运维监控以及安全体系,打造了一个安全、高效、高可用的业务中台,连接了临床、非临床、Iot、智慧医院等多个应用场景。
– InterSystems 平台是一个非常优秀的集成平台,借助该技术,给我们业务带来了非常大的便于。我也希望这么优秀的技术,能给更多的兄弟单位和合作伙伴创造价值。我也希望能够在社区与大家一起交流,分享自己的一些实践经验;同时也希望借助这个平台,向大家学习一些优秀的实践。我们一起成长,共同进步!
热烈欢迎!
感谢@黎卫东(Weidong Li),期待您成为一名优秀的新版主! 👏 Welcome @Weidong.Li ! 热烈欢迎黎老师!
文章
姚 鑫 · 七月 14, 2021
# 第三章 处理文件和目录名
`%Library.File`类提供了几个可用于处理文件名和目录名的类方法。在大多数情况下,文件和目录不需要存在即可使用这些方法。
## 获取文件名和目录名
`%Library.File`类提供可用于获取部分文件名和目录名的类方法。
在给定完整路径名的情况下,使用`GetDirectory()`和`GetFilename()`分别获取目录和短文件名。对于此方法,不允许使用部分目录名。
```java
DHC-APP>set filename = "e:\temp\config.txt"
DHC-APP>write ##class(%File).GetDirectory(filename)
E:\temp\
DHC-APP>write ##class(%File).GetFilename(filename)
config.txt
```
在给定文件名的情况下,使用`CanonicalFilename()`从根目录获取完整路径:
```java
DHC-APP>set filename = "cache.dat"
DHC-APP>write ##class(%File).CanonicalFilename(filename)
e:\dthealth\db\dthis\data\cache.dat
DHC-APP>write ##class(%File).CanonicalFilename("foo.dat")
```
如果文件无法打开,`CanonicalFilename()`方法将返回空字符串。
给定一个目录名,使用`ComputeFullDBDir()`构造目录名的规范形式。
```java
DHC-APP>write ##class(%File).ComputeFullDBDir("foodirectory")
C:\InterSystems\Cache\mgr\foodirectory\
```
在给定目录名的情况下,使用`GetDirectoryLength()`和`GetDirectoryPiess()`分别获取目录中的片断数和特定片断的片断数。片断可以用斜杠(`/`)或反斜杠(`\`)分隔,具体取决于操作系统。
```java
DHC-APP>set dir = "e:\temp"
DHC-APP>write ##class(%File).GetDirectoryLength(dir)
2
DHC-APP>write ##class(%File).GetDirectoryPiece(dir,1)
E:
```
在给定文件名或目录名的情况下,使用`ParentDirectoryName()`获取父目录。
```java
DHC-APP>set dir = "stream"
DHC-APP>write ##class(%File).ParentDirectoryName(dir)
E:\DtHealth\db\dthis\data\
````
## 规范化文件名和目录名
`%Library.File`类提供返回规范化文件名和目录名的类方法(遵循运行服务器的操作系统的命名规则)。当通过将名称片段附加到现有名称来创建新的文件名和目录名时,这些选项非常有用。
给定一个文件名,`NormalizeFilename()`返回规范化的文件名.
给定目录名,`NormalizeDirectory()`返回规范化的目录名。
这些方法返回适合在底层操作系统上使用的规范化名称,并将尝试标准化斜杠(`/`)或反斜杠(`\`)路径分隔符。
Windows示例:
```java
DHC-APP>write ##class(%File).NormalizeDirectory("stream")
E:\DtHealth\db\dthis\data\stream\
DHC-APP>write ##class(%File).NormalizeFilename("c:\temp//config.txt")
C:\temp\config.txt
```
UNIX示例:
```java
USER>set filename = "/tmp//samples/myfile.txt"
USER>write ##class(%File).NormalizeFilename(filename)
/tmp/samples/myfile.txt
USER>write ##class(%File).NormalizeDirectory("stream")
/InterSystems/IRIS/mgr/user/stream/
```
在调用这些方法之一以规范化相对于指定目录的目录名或文件名时,请添加第二个参数。该目录必须存在。
Windows示例:
```java
DHC-APP>write ##class(%File).NormalizeFilename("config.txt", "e:\temp")
E:\temp\config.txt
DHC-APP>write ##class(%File).NormalizeDirectory("stream", "")
E:\DtHealth\db\dthis\data\stream\
```
Unix示例:
```java
USER>write ##class(%File).NormalizeFilename("myfile.txt", "/tmp/samples")
/tmp/samples/myfile.txt
USER>write ##class(%File).NormalizeDirectory("stream", "")
/InterSystems/IRIS/mgr/user/stream/
```
`SubDirectoryName()`方法类似于`NormalizeDirectory()`的双参数形式,只是参数的顺序相反。此外,该目录不需要存在。在第三个参数中传递1以添加尾部分隔符,或者传递0以省略它(默认值)。
Windows示例:
```java
DHC-APP>write ##class(%File).SubDirectoryName("C:\foobar", "samples")
C:\foobar\samples
DHC-APP>write ##class(%File).SubDirectoryName("", "stream", 1)
E:\DtHealth\db\dthis\data\stream\
```
Unix示例:
```java
USER>write ##class(%File).SubDirectoryName("/foobar", "samples")
/foobar/samples
USER>write ##class(%File).SubDirectoryName("", "stream", 1)
/InterSystems/IRIS/mgr/user/stream/
```
## 用空格处理文件和目录名
对于包含空格的文件名和目录名,请使用`NormalizeFilenameWithSpaces()`,它会根据主机平台处理路径名中的空格。与规格化文件名()和规格化目录()不同,此方法只接受一个参数,不能相对于另一个目录规格化文件或目录名,也不能相对于默认目录规格化部分文件或目录名。
在Windows系统上,如果路径名包含空格,并且文件或目录不存在,则该方法返回用双引号括起来的路径名。如果路径名包含空格,并且文件或目录确实存在,则该方法返回路径名的简短形式。如果路径名不包含空格,该方法将原封不动地返回路径名。
```java
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("C:\temp\nonexistant folder") "C:\temp\nonexistant folder"
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("C:\temp\existant folder") "C:\temp\existant folder"
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("iris.dat")
iris.dat
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("cache.dat")
cache.dat
```
在Unix系统上,如果路径名包含空格,该方法将返回用双引号括起来的路径名。如果路径名不包含空格,该方法将原封不动地返回路径名。
```java
USER>write ##class(%File).NormalizeFilenameWithSpaces("/InterSystems/my directory")
"/InterSystems/my directory"
USER>write ##class(%File).NormalizeFilenameWithSpaces("iris.dat")
iris.dat
```
## 构建和解构文件和目录名
`%Library.File`类提供的类方法允许从路径数组构造文件名,或将文件名解构为路径数组。
给定一个路径数组,`Construct()`组装路径并返回文件名。构造的文件名适合服务器平台。在没有参数的情况下调用此方法会返回默认目录。
给定一个文件名,`Deconstruct()`分解文件名并返回一个路径数组。阵列的内容适合服务器平台。
下面的Windows示例将数组目录传递给`Construction()`。最后一个数组位置中的空字符串表示返回的文件名应以`a \`结尾。
```java
USER>zwrite dirs
dirs=4
dirs(1)="C:"
dirs(2)="Temp"
dirs(3)="samples"
dirs(4)=""
USER>write ##class(%File).Construct(dirs...)
C:\Temp\samples\
```
下面的Unix示例在不带参数的情况下调用`Construction()`。该方法返回默认目录。
```java
USER>set default = ##class(%File).Construct()
USER>write default
/InterSystems/IRIS/mgr/user
```
下面的Unix示例调用`Deconstruct()`,它获取变量default中的路径并将它们存储在数组`defaultdir`中。
```java
USER>do ##class(%File).Deconstruct(default, .defaultdir)
USER>zwrite defaultdir
defaultdir=4
defaultdir(1)="InterSystems"
defaultdir(2)="IRIS"
defaultdir(3)="mgr"
defaultdir(4)="user"
```
## 获取System Manager目录
使用`ManagerDirectory()`方法获取`installdir/mgr`目录的完全限定名称。例如:
```java
DHC-APP>write ##class(%File).ManagerDirectory()
C:\InterSystems\Cache\mgr\
```
文章
姚 鑫 · 五月 8, 2021
# 第三章 使用多维存储(全局变量)(四)
# 管理事务
InterSystems IRIS提供了使用全局变量实现完整事务处理所需的基本操作。
InterSystems IRIS对象和SQL自动利用这些特性。
如果直接将事务性数据写入全局变量,则可以使用这些操作。
事务命令是`TSTART`,它定义事务的开始;
`TCOMMIT`,它提交当前事务;
和`TROLLBACK`,它将中止当前事务,并撤消自事务开始以来对全局变量所做的任何更改。
例如,下面的ObjectScript代码定义了事务的开始,设置了一些全局变量节点,然后根据`ok`的值提交或回滚事务:
```java
/// w ##class(PHA.TEST.Global).GlobalTro(0)
ClassMethod GlobalTro(ok)
{
TSTART
Set ^Data(1) = "Apple1"
Set ^Data(2) = "Berry1"
If (ok) {
TCOMMIT
}
Else {
TROLLBACK
}
zw ^Data
q ""
}
```
TSTART在InterSystems IRIS日志文件中写入事务开始标记。
这定义了事务的起始边界。
在上面的示例中,如果变量`ok`为`true`(非零),则`TCOMMIT`命令标记事务成功结束,并将事务完成标记写入日志文件。
如果`ok`为`false(0)`,那么`TROLLBACK`命令将撤消自事务开始以来进行的每一个`set`或`kill`操作。
在这种情况下,`^Data(1)`和`^Data(2)`被恢复到原来的值。
**注意,在事务成功完成时,不会写入任何数据。
这是因为事务期间对数据库的所有修改都是在事务过程中正常执行的。
只有在回滚的情况下,数据库中的数据才会受到影响。
这意味着本例中的事务具有有限的隔离性;
也就是说,其他进程可以在事务提交之前看到修改后的全局值。
这通常被称为未提交的读取。
这是好是坏取决于应用程序的需求;
在许多情况下,这是完全合理的行为。
如果应用程序需要更高级别的隔离,则可以通过使用锁来实现。
这将在下一节中进行描述。**
## 锁和事务
要创建隔离事务-也就是说,为了防止其他进程在提交事务之前看到修改的数据-需要使用锁。在ObjectScript中,可以通过`lock`命令直接获取和释放锁定。锁按照约定工作;对于给定的数据结构(如用于持久对象),所有需要锁的代码都使用相同的逻辑锁引用(即,锁命令使用相同的地址)。
在事务中,锁有一个特殊的行为;
在事务过程中获取的任何锁在事务结束之前都不会被释放。
要了解为什么会这样,请考虑典型事务执行的操作:
1. 使用`TSTART`启动事务。
2. 获取要修改的一个或多个节点上的锁。这通常被称为“写”锁。
3. 修改一个或多个节点。
4. 释放锁(或多个锁)。因为我们处于事务中,所以这些锁在此时实际上不会被释放。
5. 使用`TCOMMIT`提交事务。此时,上一步中释放的所有锁实际上都已释放。
如果另一个进程想要查看此事务中涉及的节点,并且不想看到未提交的修改,则它只需在从节点读取数据之前测试锁(称为“读”锁)。因为写锁定一直保持到事务结束,所以在事务完成(提交或回滚)之前,读取进程看不到数据。
大多数数据库管理系统使用类似的机制来提供事务隔离。InterSystems IRIS的独特之处在于它让开发人员可以使用这种机制。这使得有可能为新的应用程序类型创建自定义数据库结构,同时仍然支持事务。当然,可以简单地使用InterSystems IRIS对象或SQL来管理数据,并让事务得到自动管理。
## 对TSTART的嵌套调用
InterSystems IRIS维护一个特殊的系统变量`$TLEVEL`,该变量跟踪`TSTART`命令被调用的次数。`$TLEVEL`从值`0`开始;每次调用`TSTART`时,`$TLEVEL`的值递增`1`,而每次调用`TCOMMIT`时,`$TLEVEL`的值递减`1`。如果调用`TCOMMIT`导致将`$TLEVEL`设置回`0`,则事务结束(以`COMMIT`结束)。
调用`TROLLBACK`命令总是终止当前事务,并将`$TLEVEL`设置回`0`,而不管`$TLEVEL`的值是多少。
此行为使应用程序能够将事务包装在本身包含事务的代码(如对象方法)周围。例如,持久对象提供的`%Save`方法始终将其操作作为事务执行。通过显式调用`TSTART`和`TCOMMIT`,可以创建包含几个对象保存操作的更大事务:
```java
TSTART
Set sc = object1.%Save()
If ($$$ISOK(sc)) {
// 第一次保存有效,执行第二次保存
Set sc = object2.%Save()
}
If ($$$ISERR(sc)) {
// 其中一个保存失败,正在回滚
TROLLBACK
}
Else {
// 提交
TCOMMIT
}
```
# 管理并发性
设置或检索单个全局变量节点的操作是原子的;它可以保证始终成功并获得一致的结果。对于多个节点上的操作或控制事务隔离,InterSystems IRIS提供获取和释放锁的功能。
锁由IRIS锁管理器管理。在ObjectScript中,可以通过`lock`命令直接获取和释放锁定。(InterSystems IRIS对象和SQL根据需要自动获取和释放锁)。
# 检查最新的全局变量引用
**最新的全局变量引用记录在ObjectScript `$ZREFERENCE`特殊变量中。`$ZREFERENCE`包含最新的全局引用,包括下标和扩展全局引用(如果指定)。请注意,`$ZREFERENCE`既不指示全局引用是否成功,也不指示指定的全局是否存在。InterSystems IRIS只记录最近指定的全局引用。**
## 裸全球变量引用
在带下标的全局引用之后,InterSystems IRIS会将裸指示符设置为该全局名称和下标级别。然后,可以使用裸全局引用(省略全局名称和更高级别的下标)对相同的全局变量和下标级别进行后续引用。这简化了在相同(或更低)下标级别对相同全局变量的重复引用。
在裸引用中指定较低的下标级别会将裸指示符重置为该下标级别。因此,在使用裸全局变量引用时,始终使用由最新全局引用建立的下标级别。
裸指示符值记录在`$ZREFERENCE`特殊变量中。裸露指示符被初始化为空字符串。在未设置裸指示器的情况下尝试裸全局引用会导致`` 错误。更改命名空间会重新初始化裸体指示符。可以通过将`$ZREFERENCE`设置为空字符串(`“”`)来重新初始化裸指示符。
在下面的示例中,第一个引用中指定了带下标的GLOBAL `^Produce(“fruit”,1)`。InterSystems IRIS将此全局变量名称和下标保存在裸体指示符中,以便后续的裸体全局引用可以省略全局名称`“Production”`和更高下标级别的`“Fruit”`。当`^(3,1)`裸引用达到更低的下标级别时,此新的下标级别将成为任何后续裸全局变引用的假设。
```java
/// w ##class(PHA.TEST.Global).GlobalNake()
ClassMethod GlobalNake()
{
SET ^Produce("fruit",1)="Apples" /* 完整的全局变量引用 */
SET ^(2)="Oranges" /* 裸全局变量全局引用 */
SET ^(3)="Pears" /* 假设下标级别为2 */
SET ^(3,1)="Bartlett pears" /* 转到下标级别3 */
SET ^(2)="Anjou pears" /* 假设下标级别为3 */
WRITE "latest global reference is: ",$ZREFERENCE,!
ZWRITE ^Produce
KILL ^Produce
q ""
}
```
```java
DHC-APP>w ##class(PHA.TEST.Global).GlobalNake()
latest global reference is: ^Produce("fruit",3,2)
^Produce("fruit",1)="Apples"
^Produce("fruit",2)="Oranges"
^Produce("fruit",3)="Pears"
^Produce("fruit",3,1)="Bartlett pears"
^Produce("fruit",3,2)="Anjou pears"
```
除了极少数例外,每个全局变量变引用(全引用或裸引用)都会设置裸指示器。`$ZREFERENCE`特殊变量包含最新全局变引用的完整全局名称和下标,即使这是一个裸全局引用。`ZWRITE`命令还显示每个全局的完整全局名称和下标,无论它是否使用裸引用设置。
应谨慎使用裸全局变量引用,因为InterSystems IRIS在不总是明显的情况下设置裸指示器,包括以下情况:
- 完整全局变量引用最初设置裸露指示符,随后的完整全局引用或裸露全局引用会更改裸露指示符,即使全局引用不成功。例如,试图写入不存在的全局变量的值会设置裸指示符。
- 无论InterSystems IRIS如何计算后置条件,引用下标全局的后置条件命令都会设置裸指示符。
- 引用下标全局变量的可选函数参数可能设置或不设置裸指示符,具体取决于IRIS是否计算所有参数。例如,`$get`的第二个参数总是设置裸指示符,即使它包含的默认值没有使用。InterSystems IRIS按从左到右的顺序计算参数,因此最后一个参数可能会重置由第一个参数设置的裸指示符。
- 回滚事务的`TROLLBACK`命令不会将裸指示符回滚到事务开始时的值。
如果完整全局变量引用包含扩展全局变量引用,则后续的裸全局变量引用将采用相同的扩展全局引用;不必将扩展引用指定为裸全局引用的一部分。
问题
Botai Zhang · 四月 13, 2021
在使用过程中,碰到对接一些国内编码例如:GBK2312等系列的编码格式,碰到这类情况,应该如何处理?各位有没有好的解决方式?期待解答交流! 如果需要在InterSystems IRIS中对不同的编码的数据进行转换,可以使用函数$ZCVT。 例如将变量tStr的unicode值转换为GB2312:
s tOutput=$ZCVT(tStr,"O","GB2312") 感谢回复!这种方式尝试过,但是,$ZCVT并不支持GB2312。
用GB18030,它向后兼容GB2312
公告
Michael Lei · 六月 22, 2022
Hi 社区,
这是海外工程师做的一个纯浏览器的代码编辑器CloudStudio. 欢迎大家下载试用:
GitHub 下载:
https://github.com/SeanConnelly/CloudStudio
InterSystems 应用市场下载:https://openexchange.intersystems.com/package/CloudStudio
到Discord 讨论区:https://discord.gg/ZnvdMywsjP
Docker 支持与在线Demo:
要求
已安装 git 和 Docker desktop .
安装
Clone/git 把 repo 导入任何本地目录
git https://github.com/rcemper/Dataset-OEX-reviews.git
启动IRIS容器:
docker-compose up -d --build
如何测试
http://localhost:42773/cloudstudio/CloudStudio.Index.cls
或使用在线Demo
Demo 视频:https://www.youtube.com/watch?v=Am6QAvrPPPg