Java 如何在运行时创建多个架构连接?
我有一个项目名称下拉列表,并根据所选的值生成一个模式下拉列表 生成架构列表后,会有一个“选择文件”选项,其中会选择一个脚本名,该脚本名将在多个架构上运行 项目列表值和架构列表值都存储在数据库中。数据库中还有另一个存储架构凭据的表 我想知道如何在这些多个模式上创建连接,以及如何在从该模式下拉列表中选择的多个模式中运行脚本 我已经使用iBatis框架使用Java 如何在运行时创建多个架构连接?,java,oracle,jdbc,ibatis,jdbc-odbc,Java,Oracle,Jdbc,Ibatis,Jdbc Odbc,我有一个项目名称下拉列表,并根据所选的值生成一个模式下拉列表 生成架构列表后,会有一个“选择文件”选项,其中会选择一个脚本名,该脚本名将在多个架构上运行 项目列表值和架构列表值都存储在数据库中。数据库中还有另一个存储架构凭据的表 我想知道如何在这些多个模式上创建连接,以及如何在从该模式下拉列表中选择的多个模式中运行脚本 我已经使用iBatis框架使用scriptrunner方法在一个模式中执行了代码 表1:ProjectName PROJECT_PK, PROJECT_CODE, PROJECT
scriptrunner
方法在一个模式中执行了代码
表1:ProjectName
PROJECT_PK,
PROJECT_CODE,
PROJECT_NAME
COMPONENT_PK,
COMPONENT_CODE,
COMPONENT_NAME,
PROJECT_PK
表2:ComponentName
PROJECT_PK,
PROJECT_CODE,
PROJECT_NAME
COMPONENT_PK,
COMPONENT_CODE,
COMPONENT_NAME,
PROJECT_PK
表3:SchemaName
(此表包含其他架构的凭据)
表4:项目详细信息
PROJECT_DETAIL_PK,
COMPONENT_PK,
SCHEMA_PK
表5:组件详细信息
COMPONENT_DETAILS_PK,
PROJECT_PK,
SCHEMA_PK
我附加的情景图像
我建议您创建一个“超级模式”,在每个其他模式上都有适当的授权,并为这个“超级模式”创建您的JDBC连接。这将使您需要对sql脚本进行一些修改—您需要使用一些标记来编写它,以便轻松地替换模式,例如
ALTER TABLE ${SCHEMA_MARKER}.INVOICES ADD CLIENT_ADRRESS Varchar2(35);
您的java代码将用它代替您所针对的模式。通过一些想象,您可以扩展这个想法,在所有模式上执行批量DDL脚本
顺便说一下,我从你的问题中了解到,你有许多具有相同结构的模式。我曾经被迫与这样一个遗留结构一起工作,因此我知道在公司结构中有很多动力;尽管如此,我还是建议你重新设计这样的系统。例如,在超级模式上创建物化视图时,复制模式结构,但在每个表主键中都有一个新字段(这个新字段将填补空白,使任何人都可以首先在许多模式中分离数据)
这肯定会使您的查询缓存受到的影响小得多,并且会使需要处理“分布式”数据的任何新软件的开发变得更容易。在Oracle中,模式基本上就是用户。因此,要在模式
SX
中创建表FOO
,只需以用户SX
身份登录并执行create table FOO(…)
(不指定模式)。Oracle中的user==模式约定将确保这一点有效
要以用户身份登录SX
,请抓住您的数据源
,并使用而不是默认的getConnection()
另一种方法是在脚本中添加占位符,首先处理该占位符以生成有效的SQL。请参见Jorge_B的答案以获取示例
最后,您可以使用
ALTER SESSION
(请参阅)更改默认模式。这种方法的问题是,当使用带有数据源的web容器时,必须在关闭连接之前还原架构-在这种情况下,连接永远不会真正关闭,因此,下一段请求连接的代码将得到一个意外的默认模式->难以找到的错误。下面是DAO类,用于在运行时在同一数据库上创建多个模式连接
我们需要在运行时输入模式名,并在某个servlet中调用它
模式详细信息(即用户名、密码、主机Id、端口Id和SID)将存储在数据库表中,通过这些表将创建连接
创建的连接存储在列表中,可在以后使用
此处的凭证DTO是映射到数据库中的数据库表的对象,然后
Connection conn=DBUtil.getConnection(constants.DB_DS_NAME);
Statement stmt=null;
stmt=conn.createStatement();
ResultSet rs= null;
Connection [] con=new Connection[schemaname.length];
int i,j;
String [] url=new String[schemaname.length];
String [] username=new String[schemaname.length];
String [] password=new String[schemaname.length];
List<CredentialDTO> creDTOlist=new ArrayList<CredentialDTO>();
String query1="insert into dba_project_master VALUES(9,'abc','abc','abc','abc',40)";
String query2="CREATE TABLE EMP(EMPNO NUMBER(4,0) NOT NULL ENABLE,ENAME VARCHAR2(10 BYTE),JOB VARCHAR2(9 BYTE), SAL NUMBER(7,2),DEPTNO NUMBER(2,0))";
try
{
for(i=0;i<schemaname.length;i++){
String query=" select * from dba_schema_details where schema_name="+DBUtil.enquoteString(schemaname[i]);
rs=stmt.executeQuery(query);
while(rs.next()){
CredentialDTO creDTO=new CredentialDTO();
creDTO.setSCHEMA_PK(rs.getString("SCHEMA_PK"));
creDTO.setSCHEMA_NAME(rs.getString("SCHEMA_NAME"));
creDTO.setPASSWORD(rs.getString("PASSWORD"));
creDTO.setORACLE_SID(rs.getString("ORACLE_SID"));
creDTO.setHOST_NAME(rs.getString("HOST_NAME"));
creDTO.setPORT_ID(rs.getString("PORT_ID"));
creDTOlist.add(creDTO);
}
}
System.out.println("creDTOlist size:"+creDTOlist.size());
//create URL for the schema name
int m=creDTOlist.size();
Iterator<CredentialDTO> LItr= creDTOlist.iterator();
String [] username1=new String[m];
String [] password1=new String[m];
i=0;
while(LItr.hasNext()){
System.out.println("iteration "+i);
CredentialDTO temp = LItr.next();
String URL="jdbc:oracle:thin:@"+temp.getHOST_NAME()+":"+temp.getPORT_ID()+":"+temp.getORACLE_SID();
System.out.println("URL:"+URL);
username1[i]=temp.getSCHEMA_NAME();
System.out.println("iteartion "+i+" username="+username1[i]);
password1[i]=temp.getPASSWORD();
System.out.println("iteartion "+i+" password="+password1[i]);
Class.forName("oracle.jdbc.OracleDriver");
con[i]=DriverManager.getConnection(URL, username1[i], password1[i]);
System.out.println("Connection Name:" +con[i]);
Statement st1=con[i].createStatement();
con[i].setAutoCommit(false);
st1.addBatch(query1);
st1.addBatch(query2);
int [] update=st1.executeBatch();
i++;
}
}
catch(Exception ex){
ex.printStackTrace();
}finally
{
if (conn != null) try{conn.close();} catch(SQLException ignore) {}
if (stmt!= null) try{stmt.close();} catch(SQLException ignore) {}
if (rs != null) try{rs.close();} catch(SQLException ignore) {}
}
return creDTOlist;
}
}
Connection conn=DBUtil.getConnection(constants.DB\u DS\u NAME);
语句stmt=null;
stmt=conn.createStatement();
结果集rs=null;
Connection[]con=新连接[schemaname.length];
int i,j;
String[]url=新字符串[schemaname.length];
String[]用户名=新字符串[schemaname.length];
String[]password=新字符串[schemaname.length];
List creDTOlist=new ArrayList();
字符串query1=“插入dba_项目_主值(9,'abc','abc','abc',40)”;
String query2=“创建表EMP(EMPNO编号(4,0)非空启用、ENAME VARCHAR2(10字节)、作业VARCHAR2(9字节)、SAL编号(7,2)、DEPTNO编号(2,0))”;
尝试
{
对于(i=0;i使用DDL作为“下拉列表”的简写是令人困惑的,因为在广泛理解为“数据定义语言”的数据库上下文中,尤其是在这里,您讨论的是模式。(还不清楚针对所选架构运行的SQL脚本是DML还是DDL,尽管这可能不太重要,但给人的印象是它们将是DDL)。很抱歉造成混淆,但我在括号中写道DDL在这里表示dropdownlist。sql脚本可能包含DML、DDL或DCL中的任何一种。存储架构密码似乎不是一个好主意;当您阅读这些密码时,您的连接方式是什么,或者任何人都可以看到它们?始终以对所有架构具有权限的同一用户的身份连接,似乎更安全、更安全更简单;在执行每个脚本之前,您可以这样做?不过,该用户必须具有在不同模式中运行DDL的特权。