是否可以使用 JDBC 从 ANYDATA 同步捕获队列中出队?
Is it possible to dequeue from ANYDATA Synchronous Capture queue using JDBC?
我想做的是使用 Synchronous Capture 从 Java 进程订阅 Oracle table 中的所有更改。
ANYDATA 队列是用
创建的
BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'hcb_qtab_any',
queue_name => 'hcb_queue_any',
queue_user => 'gguser');
END;
然后我使用 Dequeue using Java for Oracle 11g queue 中的代码作为示例。我正在努力
message = queue.dequeue(deq_option, XMLType.getORADataFactory());
但我得到的只是 oracle.AQ.AQOracleSQLException
:创建描述符时出错:Invalid arguments
。事实证明,我对它进行了一些调试,因为 ANYDATA TypeDescriptor.getTypeDescriptor()
将 return OpaqueDescriptor 不被视为 StructDescriptor.isValidObject()
.
我又拍了一张薄片 JDBC AQ:
AQDequeueOptions deqopt = new AQDequeueOptions();
deqopt.setConsumerName("subscriber1");
AQMessage msg = conn.dequeue("hcb_queue_any", deqopt, "SYS.ANYDATA");
OPAQUE opq = (OPAQUE)msg.getANYDATAPayload().accessDatum();
我在这里遇到了一个新的独特问题。这个OPAQUE有getDescriptor().getTypeName() == "XMLTYPE"
,所以我很想把它变成XML。但是有一个问题:只有瘦JDBC驱动支持AQ,而只有ACI驱动支持将OPAQUE转为XML。当我尝试执行 new XMLType(opq)
时出现 Only LOB or String Storage is supported in Thin XMLType
错误
如何使用 JDBC 从 AQ 中获取 Synchronous Capture XML?
您可以编写一个存储过程并使 PL/SQL 中的消息出列并将其转换为 XML 文本和 return 作为 CLOB。然后您可以使用 JDBC 从 Java 调用存储过程。当普通 AQ API 缺少功能时,我之前使用过类似的解决方法。
示例:
create or replace procedure dequeue_lcr(
p_queue_name varchar2,
p_consumer varchar2,
p_wait_seconds number,
p_lcr out clob) as
deq_lcr anydata;
deq_xml xmltype;
msgid raw(16);
deqopt dbms_aq.dequeue_options_t;
mprop dbms_aq.message_properties_t;
no_messages exception;
pragma exception_init (no_messages, -25228);
begin
deqopt.consumer_name := p_consumer;
deqopt.wait := p_wait_seconds;
deqopt.navigation := dbms_aq.first_message;
deqopt.dequeue_mode := dbms_aq.remove;
begin
dbms_aq.dequeue(
queue_name => p_queue_name,
dequeue_options => deqopt,
message_properties => mprop,
payload => deq_lcr,
msgid => msgid);
deq_xml := dbms_streams.convert_lcr_to_xml(deq_lcr);
p_lcr := deq_xml.getclobval();
commit;
exception
when no_messages then
p_lcr := null;
end;
end;
当我使用适当的队列和消费者从 PL/SQL 调用它时,这有效:
declare
v_clob clob;
begin
dequeue_lcr('aqtest.hcb_queue_any', 'LOCAL_AGENT', 5, v_clob);
if (v_clob is not null) then
dbms_output.put_line('Data: ' || v_clob);
else
dbms_output.put_line('No messages');
end if;
end;
只需使用带有 clob 作为输出参数的 CallableStatement 从 Java 进行调用,您就可以开始了!
我想做的是使用 Synchronous Capture 从 Java 进程订阅 Oracle table 中的所有更改。
ANYDATA 队列是用
创建的BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'hcb_qtab_any',
queue_name => 'hcb_queue_any',
queue_user => 'gguser');
END;
然后我使用 Dequeue using Java for Oracle 11g queue 中的代码作为示例。我正在努力
message = queue.dequeue(deq_option, XMLType.getORADataFactory());
但我得到的只是 oracle.AQ.AQOracleSQLException
:创建描述符时出错:Invalid arguments
。事实证明,我对它进行了一些调试,因为 ANYDATA TypeDescriptor.getTypeDescriptor()
将 return OpaqueDescriptor 不被视为 StructDescriptor.isValidObject()
.
我又拍了一张薄片 JDBC AQ:
AQDequeueOptions deqopt = new AQDequeueOptions();
deqopt.setConsumerName("subscriber1");
AQMessage msg = conn.dequeue("hcb_queue_any", deqopt, "SYS.ANYDATA");
OPAQUE opq = (OPAQUE)msg.getANYDATAPayload().accessDatum();
我在这里遇到了一个新的独特问题。这个OPAQUE有getDescriptor().getTypeName() == "XMLTYPE"
,所以我很想把它变成XML。但是有一个问题:只有瘦JDBC驱动支持AQ,而只有ACI驱动支持将OPAQUE转为XML。当我尝试执行 new XMLType(opq)
Only LOB or String Storage is supported in Thin XMLType
错误
如何使用 JDBC 从 AQ 中获取 Synchronous Capture XML?
您可以编写一个存储过程并使 PL/SQL 中的消息出列并将其转换为 XML 文本和 return 作为 CLOB。然后您可以使用 JDBC 从 Java 调用存储过程。当普通 AQ API 缺少功能时,我之前使用过类似的解决方法。
示例:
create or replace procedure dequeue_lcr(
p_queue_name varchar2,
p_consumer varchar2,
p_wait_seconds number,
p_lcr out clob) as
deq_lcr anydata;
deq_xml xmltype;
msgid raw(16);
deqopt dbms_aq.dequeue_options_t;
mprop dbms_aq.message_properties_t;
no_messages exception;
pragma exception_init (no_messages, -25228);
begin
deqopt.consumer_name := p_consumer;
deqopt.wait := p_wait_seconds;
deqopt.navigation := dbms_aq.first_message;
deqopt.dequeue_mode := dbms_aq.remove;
begin
dbms_aq.dequeue(
queue_name => p_queue_name,
dequeue_options => deqopt,
message_properties => mprop,
payload => deq_lcr,
msgid => msgid);
deq_xml := dbms_streams.convert_lcr_to_xml(deq_lcr);
p_lcr := deq_xml.getclobval();
commit;
exception
when no_messages then
p_lcr := null;
end;
end;
当我使用适当的队列和消费者从 PL/SQL 调用它时,这有效:
declare
v_clob clob;
begin
dequeue_lcr('aqtest.hcb_queue_any', 'LOCAL_AGENT', 5, v_clob);
if (v_clob is not null) then
dbms_output.put_line('Data: ' || v_clob);
else
dbms_output.put_line('No messages');
end if;
end;
只需使用带有 clob 作为输出参数的 CallableStatement 从 Java 进行调用,您就可以开始了!