如何在不同的CAP项目中共享表格(实例教程)

316 阅读3分钟

简介

这篇博客的目的是展示不同的CAP项目中的几种表共享模式。我已经使用CAP大约一年了,但我还是HANA数据库的新手,所以希望大家能提出意见和建议。

场景

我想出了以下方案。
每个淡蓝色的盒子代表一个CAP项目,最左边的盒子里的 "Customers "是要被重用的实体。

* 请记住,这些方案纯粹是为了学习。在有些情况下,消费OData服务比直接访问数据库更合适。

  1. 一个与被重用的实体共享相同的HDI容器和命名空间的项目
  2. 一个项目共享相同的HDI容器,但使用与重用实体不同的命名空间
  3. 一个使用与被重用实体不同的HDI容器的项目
  4. 一个与被重用的实体在不同空间的项目

总结

下面的矩阵显示了每种情况下所需的工件的概况。

在下面的章节中,我将展示每个项目的设置。这些项目是使用HANA云计算试验开发的。整个代码可在下面的GitHub存储库中找到。

github.com/miyasuta/ca…

完成设置后,你可以从OData服务中访问重用的实体,可以使用/Customers/<mainenity>?$expand=customer 端点。

情景1

当你的项目与重用实体共享同一个HDI容器和命名空间时,你需要。

  • @cds.persistence.exists 注释重复使用的实体。
namespace master.partners;

entity Vendors {
    key ID: Integer;
    name: String;
    customer: Association to Customers
}

@cds.persistence.exists
entity Customers {
    key ID: Integer;
    name: String
}
  • 使用与被重用实体相同的HDI容器服务实例。在mta.yaml中,指定资源类型为org.cloudfoundry.existing-service
resources:
 - name: master-db
   type: org.cloudfoundry.existing-service
   parameters:
     service-name: master-db   

情景 2

当你的项目共享同一个HDI容器,但使用与重用实体不同的命名空间时,你需要。

  • @cds.persistence.exists 注释重复使用的实体。
namespace master.orgs;

entity Plants {
    key ID: Integer;
    name: String;
    customer: Association to Customers
}

@cds.persistence.exists
entity Customers {
    key ID: Integer;
    name: String
}
  • 创建**.hdbsynonym**文件,以便将重用实体的名称与你的命名空间相匹配。

{
    "MASTER_ORGS_CUSTOMERS": {
        "target": {
            "object": "MASTER_PARTNERS_CUSTOMERS"
        }
    }
}
  • 使用与重用实体相同的HDI容器服务实例(与场景1相同)。

情景3

当你的项目使用与重用实体不同的HDI容器时,你需要。

  • 首先在被重用的项目中,创建角色以允许来自外部容器的访问。

*文件名可以是任何名字,只有扩展名重要。

MASTER_PARTNERS_EXTERNAL_ACCESS.hdbrole

{
    "role": {
        "name": "MASTER_PARTNERS_EXTERNAL_ACCESS",
        "object_privileges": [
            { 
                "name":"MASTER_PARTNERS_CUSTOMERS", 
                "type":"TABLE", 
                "privileges":[ "SELECT" ], 
                "privileges_with_grant_option":[] 
            }                          
        ]
    }
}

MASTER_PARTNERS_EXTERNAL_ACCESS_G.hdbrole

{
    "role": {
        "name": "MASTER_PARTNERS_EXTERNAL_ACCESS_G#",
        "object_privileges": [
            { 
                "name":"MASTER_PARTNERS_CUSTOMERS", 
                "type":"TABLE", 
                "privileges":[], 
                "privileges_with_grant_option":["SELECT"]
            }                          
        ]
    }
}

这些文件看起来很相似,唯一的区别是第一个文件有 "SELECT "的 "特权",而第二个文件有 "SELECT "的 "privileges_with_grant_option"。之后,第一个角色将被分配给新创建的HDI容器的应用程序用户,第二个角色将被分配给同一容器的对象所有者。一旦您做出上述更改,请将项目部署到 Cloud Foundry。

接下来的步骤将在 "销售 "项目中执行。

  • @cds.persistence.exists 对重复使用的实体进行注释。
namespace sales;

entity Orders {
    key ID: Integer;
    amount: Integer;
    customer: Association to Customers;
}

@cds.persistence.exists
entity Customers {
    key ID: Integer;
    name: String;
}
  • 创建**.hdbsynonym**文件,使重用实体的名称符合你的命名空间。
{
    "SALES_CUSTOMERS": {
        "target": {
            "object": "MASTER_PARTNERS_CUSTOMERS",
            "schema": "_PLACEHOLDER_"
        }
    }
}

在这种情况下,你需要指定模式,因为目标对象驻留在一个不同的模式中。但是"_PLACEHOLDER_"是从哪里来的?

为了提供模式名称,我们还需要一个文件:.hdbsynonymconfig。这个文件需要放在db/cfg下,如下图。db/cfg中的工件在部署时首先被处理。

  • 创建.hdbsynonymconfig文件以提供模式名称。
{
    "SALES_CUSTOMERS": {
        "target": {
            "object": "MASTER_PARTNERS_CUSTOMERS",
            "schema.configure": "master-db/schema"
        }
    }
}

模式名称将取自 "master-db"服务实例的 "schema "属性。

  • 创建**.hdbgrants**文件,为HDI容器用户分配角色。
{
    "master-db": {
        "object_owner": {
            "container_roles": [
                "MASTER_PARTNERS_EXTERNAL_ACCESS_G#"
            ]
        },
        "application_user": {
            "container_roles": [
                "MASTER_PARTNERS_EXTERNAL_ACCESS"
            ]
        }
    }
}

顶部的 "master-db"是重复使用的HDI容器服务实例,它是这些权限的授予者。

  • 将重复使用的实体**(master-db**)的HDI容器服务实例添加到mta.yaml中。
 # --------------------- SERVER MODULE ------------------------
 - name: sales-srv
 # ------------------------------------------------------------
   type: nodejs
   path: gen/srv
   parameters:
     buildpack: nodejs_buildpack
   requires:
    # Resources extracted from CAP configuration
    - name: sales-db
    - name: master-db 
   provides:
    - name: srv-api      # required by consumers of CAP services (e.g. approuter)
      properties:
        srv-url: ${default-url}

 # -------------------- SIDECAR MODULE ------------------------
 - name: sales-db-deployer
 # ------------------------------------------------------------
   type: hdb
   path: gen/db  
   parameters:
     buildpack: nodejs_buildpack
   properties:
     TARGET_CONTAINER: sales-db   
   requires:
    # 'hana' and 'xsuaa' resources extracted from CAP configuration
    - name: sales-db
    - name: master-db 


resources:
 # services extracted from CAP configuration
 # 'service-plan' can be configured via 'cds.requires.<name>.vcap.plan'
# ------------------------------------------------------------
 - name: sales-db
# ------------------------------------------------------------
   type: com.sap.xs.hdi-container
   parameters:
     service: hana  # or 'hanatrial' on trial landscapes
     service-plan: hdi-shared
   properties:
     hdi-service-name: ${service-name}

 - name: master-db
   type: org.cloudfoundry.existing-service
   parameters:
     service-name: master-db        

这里,两个HDI容器分别被srv模块和db部署器模块使用。为了让部署者知道哪个容器要部署项目自己的工件,属性TARGET_CONTAINER被指定。

情景四

当你的项目在与重用实体的HDI容器不同的空间时,你需要创建一个用户提供的服务,其中包含一个数据库用户,他有权限授予重用实体的访问。下面的图片显示了所需的用户和角色分配给用户。

  • 用DBADMIN用户进入数据库资源管理器,打开SQL控制台。

  • 检查角色名称和相应的模式名称。要做到这一点,请执行下面的语句。'MASTER_PARTNERS%'是我们在方案3中创建的角色名称的一部分。
select * from roles where role_name like 'MASTER_PARTNERS%';

因此,你会得到角色名称和它们的模式名称。

  • 创建一个新的数据库用户,并将上述角色分配给管理员选项。这样,这个用户就可以把 "MASTER_PARTNERS_EXTERNAL_ACESS_xx "角色授予其他容器用户。
create user UPS_GRANTOR password "UpsGrntr01" no FORCE_FIRST_PASSWORD_CHANGE;

grant "<schema_name>"."MASTER_PARTNERS_EXTERNAL_ACCESS_G#" to UPS_GRANTOR with admin option;
grant "<schema_name>"."MASTER_PARTNERS_EXTERNAL_ACCESS" to UPS_GRANTOR with admin option;
  • 现在我们已经有了一个授予者用户,在dev2空间创建一个用户提供的服务。在你的终端执行以下cf命令。
cf create-user-provided-service cross-schema-master-partners -p '{ \"user\": \"UPS_GRANTOR\", \"password\": \"UpsGrntr01\", \"driver\": \"com.sap.db.jdbc.Driver\", \"tags\": [\"hana\"], \"schema\": \"<schema_name>\" }'

* 你提供参数的方式因你的机器而异。要检查它,请执行cf create-user-provided-service -h 。这里我使用的是Windows PowerShell模式。

   Linux/Mac:
      cf.exe create-user-provided-service my-db-mine -p '{"username":"admin","password":"pa55woRD"}'

   Windows Command Line:
      cf.exe create-user-provided-service my-db-mine -p "{\"username\":\"admin\",\"password\":\"pa55woRD\"}"

   Windows PowerShell:
      cf.exe create-user-provided-service my-db-mine -p '{\"username\":\"admin\",\"password\":\"pa55woRD\"}'

剩下的步骤与方案3相似。

  • 用以下内容来注释重用的实体@cds.persistence.exists
namespace accounting;

entity Invoices {
    key ID: Integer;
    amount: Integer;
    customer: Association to Customers    
}

@cds.persistence.exists
entity Customers {
    key ID: Integer;
    name: String;
}
  • 创建**.hdbsynonym**文件,使重用实体的名称符合你的命名空间。
{
    "ACCOUNTING_CUSTOMERS": {
        "target": {
            "object": "MASTER_PARTNERS_CUSTOMERS",
            "schema": "_PLACEHOLDER_"
        }
    }
}
  • 创建**.hdbsynonymconfig**文件以提供模式名称。这个文件应该放在db/cfg下。
{
    "ACCOUNTING_CUSTOMERS": {
        "target": {
            "object": "MASTER_PARTNERS_CUSTOMERS",
            "schema.configure": "cross-schema-master-partners/schema"
        }
    }
}

模式名称将取自 "cross-schema-master-partners"服务实例的 "schema "属性,它是我们在上一步创建的用户提供的服务。

  • 创建**.hdbgrants**文件,将角色分配给HDI容器用户。
{
    "cross-schema-master-partners": {
        "object_owner": {
            "container_roles": [
                "MASTER_PARTNERS_EXTERNAL_ACCESS_G#"
            ]
        },
        "application_user": {
            "container_roles": [
                "MASTER_PARTNERS_EXTERNAL_ACCESS"
            ]
        }
    }
}
  • 将用户提供的服务实例**(cross-container-master-partners**)添加到mta.yaml。
# --------------------- SERVER MODULE ------------------------
 - name: accounting-srv
# ------------------------------------------------------------
   type: nodejs
   path: gen/srv
   parameters:
     buildpack: nodejs_buildpack
   requires:
    # Resources extracted from CAP configuration
    - name: accounting-db
    - name: cross-schema-master-partners #add
   provides:
    - name: srv-api      # required by consumers of CAP services (e.g. approuter)
      properties:
        srv-url: ${default-url}

 # -------------------- SIDECAR MODULE ------------------------
 - name: accounting-db-deployer
 # ------------------------------------------------------------
   type: hdb
   path: gen/db  
   parameters:
     buildpack: nodejs_buildpack 
   requires:
    # 'hana' and 'xsuaa' resources extracted from CAP configuration
    - name: accounting-db
    - name: cross-schema-master-partners #add


resources:
 # services extracted from CAP configuration
 # 'service-plan' can be configured via 'cds.requires.<name>.vcap.plan'
# ------------------------------------------------------------
 - name: accounting-db
# ------------------------------------------------------------
   type: com.sap.xs.hdi-container
   parameters:
     service: hana  # or 'hanatrial' on trial landscapes
     service-plan: hdi-shared
   properties:
     hdi-service-name: ${service-name}      

 - name: cross-schema-master-partners
   type: org.cloudfoundry.existing-service
   parameters:
      service-name: cross-schema-master-partners

总结

在这篇博客中,我解释了在不同CAP项目中共享表的四种模式。

  • 与重用实体共享同一HDI容器和命名空间的项目

    • 不需要特殊的设置。只要使用相同的HDI容器服务实例作为重复使用的实体。
  • 一个共享相同的HDI容器的项目,但使用与重用实体不同的命名空间

    • 需要.hdbsynonym来使重用实体的名字空间与你的名字空间相适应。
  • 一个使用与被重用实体不同的HDI容器的项目

    • .hdbsynonym是必需的,以使重用的实体的名字空间与你的名字空间相适应。
    • 需要.hdbsynonymconfig来为同义词提供模式名称。
    • .hdbgrants是必需的,以授予HDI容器用户访问重用实体的权限。
  • 在与被重用实体不同的空间中的一个项目

    • 需要一个用户提供的服务 来实现跨空间的访问。
    • .hdbsynonym是必需的,以使重用实体的命名空间与你的命名空间相适应。
    • 需要.hdbsynonymconfig来为同义词提供模式名称。
    • .hdbgrants是用来给HDI容器用户分配访问重用实体的权限的。

参考资料