如何在 hsql 中为另一个架构所有者创建表

Posted

技术标签:

【中文标题】如何在 hsql 中为另一个架构所有者创建表【英文标题】:how can I create a table for another schema owner in hsql 【发布时间】:2017-10-18 21:58:29 【问题描述】:

我正在为 Spring 批处理应用程序编写测试用例。我需要设置一个镜像远程大型机 db2 数据库的 HSQL 数据库,以便我可以快速运行我的测试。

我必须设置 db 表以使以下 SQL 语句成功:

SELECT PROJ_TYP, SYS_CD, ... FROM CMNREF.CNTRCT_EXTRNL_KEY_REF_V WITH UR

我相信上面的 CMNREF 是 Schema 所有者。如何在 HSQL db 中创建该表和架构,以便此 SELECT 可以工作?

更新: 对主题here 进行了一些研究,我了解到我需要执行以下操作: 1)使用SA默认用户创建新用户CMNREF 2) 授予用户 CMNREF 一些 ROLES(即 SELECT)

但是,我也注意到默认用户 SA 具有 DBA 角色,这意味着它可以在该数据库上执行任何操作....所以我想知道我是否需要费心创建上面的 1 和 2... .

我的测试用例:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =  "/load-BMS-data-job-launcher-context.xml" )
public class SimpleJobLaunchFunctionalTests 

@Autowired
private JobLauncherTestUtils jobLauncherUtils;

@Qualifier("jdbcTemplate")
@Autowired
private JdbcOperations jdbcTemplate;

@Qualifier("jdbcTemplateBMS")
@Autowired
private JdbcOperations jdbcTemplateBMS;


@Before
public void setUp() 
    jdbcTemplateBMS.update("DELETE from CMNREF.CNTRCT_EXTRNL_KEY_REF_V");
    jdbcTemplate.update("DELETE from SHADOW_BMS");
 // jdbcTemplate.update("DELETE from CMNREF.CNTRCT_EXTRNL_KEY_REF_V");

    Calendar calendar = Calendar.getInstance();
    java.sql.Timestamp currentTimestamp = new java.sql.Timestamp(calendar.getTime().getTime());

    // Insert one test data record
    jdbcTemplate.update("INSERT INTO CMNREF.CNTRCT_EXTRNL_KEY_REF_V(PROJ_TYP_CD, SYS_CD, STAT_CK_CD, EXTRNL_KEY_CD, EXTRNL_SYS_CD, CNTRCT_NUM, PROJ_NUM, CNTRCT_LINE_ITM, CUST_NUM, CUST_CNTL_NUM, CUST_NM, CHRG_CD, PRDCT_ID, BILNG_CRNCY_CD, BILNG_ISO_CRNCY_CD, BILNG_CRNCY_DCM_NUM, CFTS_CRNCY_EXCH_RT, CFTS_CRNCY_EXCH_RT_EXPIR_DT, CHRG_CRNCY_CD, CHRG_ISO_CRNCY_CD, CTRY_CD, CMPNY_CD, OFFERING_CD, CNTL_GRP_CD, ORIG_CTRY_CD, ORIG_CMPNY_CD, ORIG_LOC_CD, NOTES_ID, INET_ID, CFTS_GBI_IND, CFTS_CHRG_TYP_CD, CFTS_SPCL_HNDL_CD, CC_PMT_METH_IND, STAT_CD, REFRESH_TMS) VALUES('PROJT1', 'SCD', 'STC', 'EXTKEY','EXTSYSCODE', 'CTR923','PROJN293', 23, 'CNUM32', 'CN', 'NAME THIS CUST', 'CHCD', '2903-920','BCD', 'BIC', 23, 1.345, '2017-01-23','CCC', 'CIC', 'CCD', 'IBM', '9203L-98', 'CTLGRP', 'USA', 'IBM001', 'OLC', 'me@us.ibm.com', 'ME/US/IBM/COM', 'G', 'T', 'H', 'P', 'OPEN', '2016-01-02 19:29:23.271' )");


我的数据库脚本在那里:

CREATE USER CMNREF PASSWORD 'pw';
CREATE SCHEMA CMNREF AUTHORIZATION DBA;

ALTER USER CMNREF SET INITIAL SCHEMA CMNREF;

SET SCHEMA CMNREF;

CREATE TABLE CMNREF.CNTRCT_EXTRNL_KEY_REF_V  (
     PROJ_TYP_CD         VARCHAR(10),                 
     SYS_CD              VARCHAR(3),                  
     STAT_CK_CD          VARCHAR(12),                  
     EXTRNL_KEY_CD       VARCHAR(36),                  
     EXTRNL_SYS_CD       VARCHAR(10),                  
     CNTRCT_NUM          VARCHAR(15),                 
     PROJ_NUM            VARCHAR(8),                 
     CNTRCT_LINE_ITM     INTEGER,              
     CUST_NUM            VARCHAR(8),                
     CUST_CNTL_NUM       VARCHAR(2),                 
     CUST_NM             VARCHAR(35),               
     CHRG_CD             VARCHAR(4),                        
     PRDCT_ID            VARCHAR(15),               
     BILNG_CRNCY_CD      VARCHAR(3),                 
     BILNG_ISO_CRNCY_CD  VARCHAR(3),             
     BILNG_CRNCY_DCM_NUM SMALLINT,           
     CFTS_CRNCY_EXCH_RT  DECIMAL,           
     CFTS_CRNCY_EXCH_RT_EXPIR_DT   DATE,
     CHRG_CRNCY_CD       VARCHAR(3),                 
     CHRG_ISO_CRNCY_CD   VARCHAR(3),              
     CTRY_CD             VARCHAR(3),                
     CMPNY_CD            VARCHAR(10),                      
     OFFERING_CD         VARCHAR(8),                   
     CNTL_GRP_CD         VARCHAR(8),                  
     ORIG_CTRY_CD        VARCHAR(3),          
     ORIG_CMPNY_CD       VARCHAR(10),                
     ORIG_LOC_CD         VARCHAR(3),                   
     NOTES_ID            VARCHAR(100),          
     INET_ID             VARCHAR(100),          
     CFTS_GBI_IND        VARCHAR(1),          
     CFTS_CHRG_TYP_CD    VARCHAR(1),               
     CFTS_SPCL_HNDL_CD   VARCHAR(1),
     CC_PMT_METH_IND     VARCHAR(1),               
     STAT_CD             VARCHAR(12),          
     REFRESH_TMS         TIMESTAMP  
) ;

我的数据源在这里定义:

    <!--  Initialise the database before every test case: -->
<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="$batch.drop.script"/>
    <jdbc:script location="$batch.schema.script"/>
    <jdbc:script location="$batch.business.schema.script"/>
</jdbc:initialize-database>

<!-- Initialize the mock BMS database  -->
<jdbc:initialize-database data-source="BMSdataSource" ignore-failures="DROPS">
    <jdbc:script location="$bmsmock.business.schema.script"/>
</jdbc:initialize-database>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="$batch.jdbc.driver" />
    <property name="url" value="$batch.jdbc.url" />
    <property name="username" value="$batch.jdbc.user" />
    <property name="password" value="$batch.jdbc.password" />
    <property name="maxActive" value="$batch.jdbc.pool.size"/>
    <property name="validationQuery" value="$batch.jdbc.validationQuery"/>
    <property name="testWhileIdle" value="$batch.jdbc.testWhileIdle"/>
</bean>

<bean id="BMSdataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="$bmsmock.jdbc.driver" />
    <property name="url" value="$bmsmock.jdbc.url" />
    <property name="username" value="$bmsmock.jdbc.user" />
    <property name="password" value="$bmsmock.jdbc.password" />
    <property name="maxActive" value="$bmsmock.jdbc.pool.size"/>
    <property name="validationQuery" value="$bmsmock.jdbc.validationQuery"/>
    <property name="testWhileIdle" value="$bmsmock.jdbc.testWhileIdle"/>
</bean> 

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" lazy-init="true">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- Set up or detect a System property called "ENVIRONMENT" used to construct a properties file on the classpath.  The default is "hsql".  -->
<bean id="environment"
    class="org.springframework.batch.support.SystemPropertyInitializer">
    <property name="defaultValue" value="hsql"/>
    <property name="keyName" value="ENVIRONMENT"/>
</bean>

<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
    depends-on="environment">
    <property name="location" value="classpath:batch-$ENVIRONMENT.properties" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="order" value="1" />
</bean>

My HSQLDB Properties are below:

batch.jdbc.driver=org.hsqldb.jdbcDriver
batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true;hsqldb.tx=mvcc
batch.jdbc.user=sa
batch.jdbc.password=
batch.jdbc.testWhileIdle=false
batch.jdbc.validationQuery=
batch.drop.script=classpath:/org/springframework/batch/core/schema-drop-hsqldb.sql
batch.schema.script=classpath:/org/springframework/batch/core/schema-hsqldb.sql
batch.business.schema.script=classpath:/db/custom-db-assets.sql
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer
batch.database.incrementer.parent=columnIncrementerParent
batch.lob.handler.class=org.springframework.jdbc.support.lob.DefaultLobHandler
batch.jdbc.pool.size=6
batch.grid.size=6
batch.verify.cursor.position=true
batch.isolationlevel=ISOLATION_SERIALIZABLE
batch.data.source.init=true
batch.table.prefix=BATCH_

bmsmock.jdbc.driver=org.hsqldb.jdbcDriver
bmsmock.jdbc.url=jdbc:hsqldb:mem:testbms;sql.enforce_strict_size=true;hsqldb.tx=mvcc
bmsmock.jdbc.user=SA
bmsmock.jdbc.password=
bmsmock.jdbc.pool.size=6
bmsmock.jdbc.testWhileIdle=false
bmsmock.jdbc.validationQuery=
bmsmock.business.schema.script=db/mock-bms-tables.sql

【问题讨论】:

上面的一些研究...... 【参考方案1】:

使用没有 DBA 角色的其他用户是个好主意。

在 HSQLDB 中,用户和模式是独立的概念,每个用户没有自动模式。你所做的很好。或者你可以

CREATE USER CMNREF PASSWORD 'pw'
CREATE SCHEMA CMNREF AUTHORIZATION CMNREF

通过上述内容,CMNREF 用户拥有同名的架构。它可以执行自己架构中的所有语句。

更新:在您的设置中,SA 用户用于所有操作。您需要使用用户 SA 运行您引用的 DB 脚本的用户创建部分,然后使用用户 CMNREF 运行测试。

【讨论】:

org.springframework.jdbc.BadSqlGrammarException: StatementCallback;错误的 SQL 语法 [INSERT INTO CNTRCT_EXTRNL_KEY_REF_V(PROJ_TYP_CD...'ME/US/IBM/COM', 'G', 'T', 'H', 'P', 'OPEN', '2016-01-02 19: 29:23.271')];嵌套异常是 java.sql.SQLSyntaxErrorException: 用户缺少权限或找不到对象: CNTRCT_EXTRNL_KEY_REF_V 我已经像这样启动了 HSQL 管理器: java -cp hsqldb.jar org.hsqldb.util.DatabaseManagerSwing 我可以在那里运行所有命令,我可以插入和选择数据......为什么不在 SpringJdbcTemplate 中? 在 DBManager 和 Spring 中使用完全相同的连接 URL 以获得相同的行为。 我做了……完全一样……这就是令人沮丧的地方。我不知道有什么不同。我看到的唯一神秘的是,我正在调用的 SQL 是这样的:“INSERT INTO CMNREF.CNTRCT_EXTRNL_KEY_REF_V(PROJ_TYP_...)”并且错误显示为:用户缺少特权或找不到对象:CNTRCT_EXTRNL_KEY_REF_V,没有架构预选赛?! 还有 INITIAL SCHEMA 的概念,由两个 SET .. INITIAL SCHEMA 语句支持,CURRENT_SCHEMA 可以通过 SET SCHEMA 语句来改变。【参考方案2】:

我的脚本(附件)显示了如何做到这一点。没错,脚本或架构定义没有错。我的问题是我的测试用例在将数据插入 CMNREF.C* 表时引用了错误的 Jdbc 模板....正确的 stmt 应该是:

jdbcTemplateBMS**.update("INSERT INTO CMNREF.CNTRCT_E

另外,我需要打开 DB2 模式才能让我的 sql 脚本正常工作

【讨论】:

以上是关于如何在 hsql 中为另一个架构所有者创建表的主要内容,如果未能解决你的问题,请参考以下文章

如何列出为 postgres 中的表创建的索引

为 hsqldb 创建架构时出现语法错误

在 PostgreSQL 中为特定模式和表所有者创建表的过程是啥

在 Bigquery 中为多个 CSV 文件自动创建表

如何创建持久化 HSQL 数据库?

如何在 Google bigquery 中为多个动态表创建授权视图?