我要做的是从Java进程使用Synchronous Capture订阅Oracle表中的所有更改。
使用
创建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()
将返回不被视为StructDescriptor.isValidObject()
的OpaqueDescriptor。
我使用瘦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。我正在尝试Only LOB or String Storage is supported in Thin XMLType
new XMLType(opq)
错误
如何使用JDBC从AQ获取Synchronous Capture XML?
答案 0 :(得分:2)
您可以编写存储过程并在PL / SQL中将消息出列并将其转换为XML文本并将其作为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调用,你就应该好了!