新用户注册入口 老用户登录入口

[转载]java监听oracle aq,透过JMS监听Oracle AQ,在数据库变化时触发执行Java程序

文章作者:转载 更新时间:2023-12-17 14:22:22 阅读数量:137
文章标签:创建队列表连接参数消息转换类入队消息出队消息
本文摘要:本文详细介绍了在Oracle 12C环境下利用高级消息队列(AQ)进行数据传输的具体步骤,从创建payload、队列表到操作队列的启动、停止与删除。首先定义了自定义类型的消息负荷payload,并使用DBMS_AQADM创建支持单个消费者的队列表demo_queue_table。进一步展示了如何通过PL/SQL进行入队和尝试出队消息的操作。同时,文章还探讨了Java通过JMS监听并处理Oracle AQ队列的方法,包括建立连接参数类和消息转换类以实现Oracle数据库与Java系统间的数据交互。此外,文中还简述了如何监控表记录变化并通过触发器通知Java应用程序。
转载文章

本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_42309178/article/details/115241521。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

环境说明

一Oracle高级消息队列AQ创建消息负荷payload

创建队列表

创建队列并启动

队列的停止和删除

入队消息

出队消息

二Java使用JMS监听并处理Oracle AQ队列创建连接参数

创建消息转换类

主类进行消息处理

三监控表记录变化通知Java创建表

创建存储过程

创建触发器

环境说明

本实验环境基于Oracle 12C和JDK1.8,其中Oracle 12C支持多租户特性,相较于之前的Oracle版本,使用‘C##用户名‘表示用户,例如如果数据库用户叫kevin,则登陆时使用C##kevin进行登陆。

一、Oracle高级消息队列AQ

Oracle AQ是Oracle中的消息队列,是Oracle中的一种高级应用,每个版本都在不断的加强,使用DBMS_AQ系统包进行相应的操作,是Oracle的默认组件,只要安装了Oracle数据库就可以使用。使用AQ可以在多个Oracle数据库、Oracle与Java、C等系统中进行数据传输。

下面分步骤说明如何创建Oracle AQ

1. 创建消息负荷payload

Oracle AQ中传递的消息被称为有效负荷(payloads),格式可以是用户自定义对象或XMLType或ANYDATA。本例中我们创建一个简单的对象类型用于传递消息。

create type demo_queue_payload_type as object (message varchar2(4000));

2. 创建队列表

队列表用于存储消息,在入队时自动存入表中,出队时自动删除。使用DBMS_AQADM包进行数据表的创建,只需要写表名,同时设置相应的属性。对于队列需要设置multiple_consumers为false,如果使用发布/订阅模式需要设置为true。

begin

dbms_aqadm.create_queue_table(

queue_table => 'demo_queue_table',

queue_payload_type => 'demo_queue_payload_type',

multiple_consumers => false

);

end;

执行完后可以查看oracle表中自动生成了demo_queue_table表,可以查看影响子段(含义比较清晰)。

3. 创建队列并启动

创建队列并启动队列:

begin

dbms_aqadm.create_queue (

queue_name => 'demo_queue',

queue_table => 'demo_queue_table'

);

dbms_aqadm.start_queue(

queue_name => 'demo_queue'

);

end;

至此,我们已经创建了队列有效负荷,队列表和队列。可以查看以下系统创建了哪些相关的对象:

SELECT object_name, object_type FROM user_objects WHERE object_name != 'DEMO_QUEUE_PAYLOAD_TYPE';

OBJECT_NAME OBJECT_TYPE

------------------------------ ---------------

DEMO_QUEUE_TABLE TABLE

SYS_C009392 INDEX

SYS_LOB0000060502C00030$$ LOB

AQ$_DEMO_QUEUE_TABLE_T INDEX

AQ$_DEMO_QUEUE_TABLE_I INDEX

AQ$_DEMO_QUEUE_TABLE_E QUEUE

AQ$DEMO_QUEUE_TABLE VIEW

DEMO_QUEUE QUEUE

我们看到一个队列带出了一系列自动生成对象,有些是被后面直接用到的。不过有趣的是,创建了第二个队列。这就是所谓的异常队列(exception queue)。如果AQ无法从我们的队列接收消息,将记录在该异常队列中。

消息多次处理出错等情况会自动转移到异常的队列,对于异常队列如何处理目前笔者还没有找到相应的写法,因为我使用的场景并不要求消息必须一对一的被处理,只要起到通知的作用即可。所以如果消息转移到异常队列,可以执行清空队列表中的数据

delete from demo_queue_table;

4. 队列的停止和删除

如果需要删除或重建可以使用下面的方法进行操作:

BEGIN

DBMS_AQADM.STOP_QUEUE(

queue_name => 'demo_queue'

);

DBMS_AQADM.DROP_QUEUE(

queue_name => 'demo_queue'

);

DBMS_AQADM.DROP_QUEUE_TABLE(

queue_table => 'demo_queue_table'

);

END;

5. 入队消息

入列操作是一个基本的事务操作(就像往队列表Insert),因此我们需要提交。

declare

r_enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T;

r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;

v_message_handle RAW(16);

o_payload demo_queue_payload_type;

begin

o_payload := demo_queue_payload_type('what is you name ?');

dbms_aq.enqueue(

queue_name => 'demo_queue',

enqueue_options => r_enqueue_options,

message_properties => r_message_properties,

payload => o_payload,

msgid => v_message_handle

);

commit;

end;

通过SQL语句查看消息是否正常入队:

select * from aq$demo_queue_table;

select user_data from aq$demo_queue_table;

6. 出队消息

使用Oracle进行出队操作,我没有实验成功(不确定是否和DBMS_OUTPUT的执行权限有关),代码如下,读者可以进行调试:

declare

r_dequeue_options DBMS_AQ.DEQUEUE_OPTIONS_T;

r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;

v_message_handle RAW(16);

o_payload demo_queue_payload_type;

begin

DBMS_AQ.DEQUEUE(

queue_name => 'demo_queue',

dequeue_options => r_dequeue_options,

message_properties => r_message_properties,

payload => o_payload,

msgid => v_message_handle

);

DBMS_OUTPUT.PUT_LINE(

'***** Browse message is [' || o_payload.message || ']****'

);

end;

二、Java使用JMS监听并处理Oracle AQ队列

Java使用JMS进行相应的处理,需要使用Oracle提供的jar,在Oracle安装目录可以找到:在linux中可以使用find命令进行查找,例如

find `pwd` -name 'jmscommon.jar'

需要的jar为:

app/oracle/product/12.1.0/dbhome_1/rdbms/jlib/jmscommon.jar

app/oracle/product/12.1.0/dbhome_1/jdbc/lib/ojdbc7.jar

app/oracle/product/12.1.0/dbhome_1/jlib/orai18n.jar

app/oracle/product/12.1.0/dbhome_1/jlib/jta.jar

app/oracle/product/12.1.0/dbhome_1/rdbms/jlib/aqapi_g.jar

1. 创建连接参数类

实际使用时可以把参数信息配置在properties文件中,使用Spring进行注入。

package org.kevin.jms;

/**

*

*@author 李文锴

* 连接参数信息

*

*/

public class JmsConfig {

public String username = "c##kevin";

public String password = "a111111111";

public String jdbcUrl = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";

public String queueName = "demo_queue";

}

2. 创建消息转换类

因为消息载荷是Oracle数据类型,需要提供一个转换工厂类将Oracle类型转换为Java类型。

package org.kevin.jms;

import java.sql.SQLException;

import oracle.jdbc.driver.OracleConnection;

import oracle.jdbc.internal.OracleTypes;

import oracle.jpub.runtime.MutableStruct;

import oracle.sql.CustomDatum;

import oracle.sql.CustomDatumFactory;

import oracle.sql.Datum;

import oracle.sql.STRUCT;

/**

*

*@author 李文锴

* 数据类型转换类

*

*/

@SuppressWarnings("deprecation")

public class QUEUE_MESSAGE_TYPE implements CustomDatum, CustomDatumFactory {

public static final String _SQL_NAME = "QUEUE_MESSAGE_TYPE";

public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

MutableStruct _struct;

// 12表示字符串

static int[] _sqlType = { 12 };

static CustomDatumFactory[] _factory = new CustomDatumFactory[1];

static final QUEUE_MESSAGE_TYPE _MessageFactory = new QUEUE_MESSAGE_TYPE();

public static CustomDatumFactory getFactory() {

return _MessageFactory;

}

public QUEUE_MESSAGE_TYPE() {

_struct = new MutableStruct(new Object[1], _sqlType, _factory);

}

public Datum toDatum(OracleConnection c) throws SQLException {

return _struct.toDatum(c, _SQL_NAME);

}

public CustomDatum create(Datum d, int sqlType) throws SQLException {

if (d == null)

return null;

QUEUE_MESSAGE_TYPE o = new QUEUE_MESSAGE_TYPE();

o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory);

return o;

}

public String getContent() throws SQLException {

return (String) _struct.getAttribute(0);

}

}

3. 主类进行消息处理

package org.kevin.jms;

import java.util.Properties;

import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.MessageListener;

import javax.jms.Queue;

import javax.jms.QueueConnection;

import javax.jms.QueueConnectionFactory;

import javax.jms.Session;

import oracle.jms.AQjmsAdtMessage;

import oracle.jms.AQjmsDestination;

import oracle.jms.AQjmsFactory;

import oracle.jms.AQjmsSession;

/**

*

*@author 李文锴 消息处理类

*

*/

public class Main {

public static void main(String[] args) throws Exception {

JmsConfig config = new JmsConfig();

QueueConnectionFactory queueConnectionFactory = AQjmsFactory.getQueueConnectionFactory(config.jdbcUrl,

new Properties());

QueueConnection conn = queueConnectionFactory.createQueueConnection(config.username, config.password);

AQjmsSession session = (AQjmsSession) conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

conn.start();

Queue queue = (AQjmsDestination) session.getQueue(config.username, config.queueName);

MessageConsumer consumer = session.createConsumer(queue, null, QUEUE_MESSAGE_TYPE.getFactory(), null, false);

consumer.setMessageListener(new MessageListener() {

@Override

public void onMessage(Message message) {

System.out.println("ok");

AQjmsAdtMessage adtMessage = (AQjmsAdtMessage) message;

try {

QUEUE_MESSAGE_TYPE payload = (QUEUE_MESSAGE_TYPE) adtMessage.getAdtPayload();

System.out.println(payload.getContent());

} catch (Exception e) {

e.printStackTrace();

}

}

});

Thread.sleep(1000000);

}

}

使用Oracle程序块进行入队操作,在没有启动Java时看到队列表中存在数据。启动Java后,控制台正确的输出的消息;通过Oracle程序块再次写入消息,发现控制台正确处理消息。Java的JMS监听不是立刻进行处理,可能存在几秒中的时间差,时间不等。

三、监控表记录变化通知Java

下面的例子创建一个数据表,然后在表中添加触发器,当数据变化后触发器调用存储过程给Oracle AQ发送消息,然后使用Java JMS对消息进行处理。

1. 创建表

创建student表,包含username和age两个子段,其中username时varchar2类型,age时number类型。

2. 创建存储过程

创建send_aq_msg存储过程,因为存储过程中调用dbms数据包,系统包在存储过程中执行需要进行授权(使用sys用户进行授权):

grant execute on dbms_aq to c##kevin;

注意存储过程中包含commit语句。

create or replace

PROCEDURE send_aq_msg (info IN VARCHAR2) as

r_enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T;

r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;

v_message_handle RAW(16);

o_payload demo_queue_payload_type;

begin

o_payload := demo_queue_payload_type(info);

dbms_aq.enqueue(

queue_name => 'demo_queue',

enqueue_options => r_enqueue_options,

message_properties => r_message_properties,

payload => o_payload,

msgid => v_message_handle

);

commit;

end send_aq_msg;

3. 创建触发器

在student表中创建触发器,当数据写入或更新时,如果age=18,则进行入队操作。需要调用存储过程发送消息,但触发器中不能包含事物提交语句,因此需要使用pragma autonomous_transaction;声明自由事物:

CREATE OR REPLACE TRIGGER STUDENT_TR

AFTER INSERT OR UPDATE OF AGE ON STUDENT FOR EACH ROW

DECLARE

pragma autonomous_transaction;

BEGIN

if :new.age = 18 then

send_aq_msg(:new.username);

end if;

END;

创建完触发器后向执行插入或更新操作:

insert into student (username,age) values ('jack.lee.3k', 18);

update student set age=18 where username='jack003';

Java JMS可以正确的处理消息。

本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_42309178/article/details/115241521。

该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。

作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。

如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。

相关阅读
文章标题:[转载][洛谷P1082]同余方程

更新时间:2023-02-18
[转载][洛谷P1082]同余方程
文章标题:[转载]webpack优化之HappyPack实战

更新时间:2023-08-07
[转载]webpack优化之HappyPack实战
文章标题:[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法

更新时间:2023-09-10
[转载]oracle 同时更新多表,在Oracle数据库中同时更新两张表的简单方法
文章标题:[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo

更新时间:2024-03-11
[转载][Unity] 包括场景互动与射击要素的俯视角闯关游戏Demo
文章标题:[转载]程序员也分三六九等?等级差异,一个看不起一个!

更新时间:2024-05-10
[转载]程序员也分三六九等?等级差异,一个看不起一个!
文章标题:[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集

更新时间:2024-01-12
[转载]海贼王 动漫 全集目录 分章节 精彩打斗剧集
名词解释
作为当前文章的名词解释,仅对当前文章有效。
Oracle高级消息队列 (AQ)Oracle Advanced Queuing (AQ) 是Oracle数据库内置的一种消息中间件服务,它允许在数据库内部或跨多个数据库、系统(如Java和C应用程序)之间高效可靠地传输和处理异步消息。AQ支持多种消息格式,包括用户自定义对象、XMLType和ANYDATA,并提供了事务性保证和灵活的消息路由机制。
JMS (Java Message Service)Java消息服务是一种Java平台的标准API,用于实现消息传递系统中的生产者-消费者模式。JMS使得Java应用程序可以发送、接收和读取消息,从而实现了分布式应用之间的解耦和异步通信。在本文的语境中,Java通过JMS与Oracle AQ集成,监听并处理队列中的消息。
PL/SQLPL/SQL是Oracle数据库特有的过程化SQL语言,它扩展了SQL的功能,允许开发人员编写包含条件判断、循环和其他复杂逻辑的存储过程、函数、触发器等数据库对象。在文章中,使用PL/SQL执行了一系列对Oracle AQ的操作,如创建队列、启动队列、入队和出队消息等。
JDBC连接参数类Java Database Connectivity (JDBC) 连接参数类是Java程序中用于存储数据库连接信息的类。在文中提到的JmsConfig类中,包含了诸如用户名、密码、数据库URL以及目标队列名称等连接参数,这些参数被用于初始化和管理到Oracle数据库的JDBC连接,以便Java应用程序能够与Oracle AQ进行交互。
CustomDatumFactory与CustomDatum在Java与Oracle数据库类型转换过程中,CustomDatumFactory和CustomDatum是Oracle JDBC驱动提供的接口和类,用于将Oracle数据库的自定义数据类型(如在本例中的demo_queue_payload_type)转换为Java对象,以便在Java应用程序中处理。CustomDatumFactory负责创建和解析CustomDatum对象,而CustomDatum则表示一个可定制的数据结构,可以与数据库中的自定义数据类型相对应。
延伸阅读
作为当前文章的延伸阅读,仅对当前文章有效。
在深入学习了Oracle高级消息队列(AQ)的创建与使用,以及如何通过Java JMS进行监听和处理后,进一步了解消息队列技术在现代企业级应用中的实践与发展显得尤为重要。近期,Oracle发布了最新版本的数据库产品,其中对AQ组件进行了多项优化升级,不仅提升了消息处理效率,还增强了与云环境和其他消息服务的集成能力。
2022年,Oracle官方博客分享了一篇题为《Oracle AQ的新特性及其在微服务架构中的应用》的文章,详细解读了Oracle 19C及更高版本中AQ的改进之处,如支持JSON格式的消息负载、更灵活的多租户管理和跨数据库的分布式队列功能等。这些新特性使得AQ能够更好地适应当前流行的微服务架构,实现不同服务间高效可靠的数据传输与同步。
此外,在开源社区层面,Apache ActiveMQ Artemis作为一款广泛采用的消息中间件,也在持续演进以满足不断变化的企业需求。其与Oracle AQ的兼容性有所提升,用户现在可以在多种场景下根据实际业务需求选择适合的消息队列解决方案。
同时,对于Java开发者而言,《Java Message Service (JMS)实战》一书提供了大量关于利用JMS进行消息传递的实战案例和最佳实践,有助于读者在实际项目中更加熟练地运用JMS与Oracle AQ结合,构建高性能、高可用的消息驱动系统。
综上所述,无论是紧跟Oracle AQ的最新发展动态,还是探究开源替代方案与相关技术书籍的学习,都将帮助开发者更好地掌握消息队列技术,并将其应用于实际工作中,以提升系统的整体性能与稳定性。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
sed 's/old/new/g' file.txt - 替换文件中的文本。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
响应式抖音课程培训学院类企业前端模板下载 01-21 jQuery点击显示隐藏更多文字内容插件 01-15 黑色设计师简历响应式网页模板下载 01-14 [转载]Tomcat启动时卡在“ Deploying web application directory ”很久的解决方法 12-19 Saiku LDAP集成登录失效问题:排查配置错误、身份验证及解决方案实操 12-01 Spring Cloud微服务架构中注册中心的必要性与服务间通信实践:服务发现、API契约与高可用性考量 11-23 MahoutIllegalArgumentException在Apache Mahout中的应用场景:矩阵维度不匹配与向量索引异常解析及参数有效性的API调用实践 10-16 [转载]Docker 相关配置文件路径 09-08 蓝色精品美容整形机构网站模板 08-29 本次刷新还10个文章未展示,点击 更多查看。
Gradle在持续集成中的关键作用:自动化构建、依赖管理与多项目构建实践及CI服务器集成 07-06 化妆品购物商城通用网站模板下载 06-27 响应式建筑装饰设计类企业前端CMS模板下载 04-14 微服务架构下用户认证鉴权:网关层统一处理与服务内部处理的比较及选择考量 04-09 响应式会议活动主题着陆页网站模板 03-24 Tomcat内存泄漏问题在Web应用程序中的解决方案:Servlet上下文管理、全局变量引用与弱引用实践及监控工具应用 03-15 Kafka消费者消费偏移量设置:auto.offset.reset策略与手动控制方法详解 02-10 [转载]JavaScript中的时间与日期、正则表达式和Function类型 01-24 大气简洁手机电子产品展示柜台前端模板 01-22 项目案例展示设计公司企业网站模板 01-18 Bootstrap博客后台管理系统网站模板 01-08
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"