因为以前从未用数据库向java接口推送数据,所以为了实现这个demo我是一步一个脚印的踩坑啊!!!
此文章的作用以及应用场景:利用数据库主动推送数据,实现前端页面数据实时更新,替换ajax轮询机制。推送的依据是,只要数据库指定的表中数据增加有了变化,数据库会触发触发器然后通过存储过程调用消息推送接口
代码如下:....
----------------------------触发器---------------------------------------
USE [devRep]
GO
/****** Object: Trigger [dbo].[tr_sm_demo] Script Date: 2019/9/26 14:06:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Description: <Insert触发器>
-- =============================================
create TRIGGER [dbo].[tr_sm_demo]
ON [dbo].[demo]
AFTER insert
AS
BEGIN
declare @id int
set @id = (select id from demo where id=@id) --如不指定条件查询 会出现 子查询返回的不是一个参数 !<> >>? 乱七八糟的一个错误 就是这里返回必须是一个数据
exec proc_useJPushAPI @id --调用存储过程并传参 如果传入的参数未变则不会触发
SET NOCOUNT ON;
END
----------------------------存储过程--------------------------------
USE [devRep]
GO
/****** Object: StoredProcedure [dbo].[proc_useJPushAPI] Script Date: 2019/9/26 13:56:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Description: <调用消息推送接口>
-- =============================================
CREATE procedure [dbo].[proc_useJPushAPI]
@id varchar(20) --demo表的id字段
AS
BEGIN
--创建存储过程里的参数
declare @url varchar(4000) --接口路由
declare @object int --OLE对象实例
declare @responseText varchar(4000) --文本
declare @name varchar(20)
select @name=name from demo; --查询demo表为接口传递参数
set @url = 'http://127.0.0.1:8080/site/recedata?name='+@name ;
print @url
exec sp_OACreate'MSXML2.XMLHTTP',@object out
exec sp_OAMethod @object,'open',null,'get',@url,'false'
exec sp_OAMethod @object,'send'
exec sp_OAMethod @object,'responseText',@responseText output
print @responseText
exec sp_OADestroy @object
SET NOCOUNT ON;
END
//接收java接口代码
@RequestMapping(value = "/recedata")
public String recedata( String name) {
try {
System.out.println("sql server 访问啦---");
return "HELLO";
} catch (Exception e) {
logger.info(e.getMessage(),e);
}
return null;
}
第二种写法
create table A(keyId int,info1 varchar(20))
go
insert into A values(1,'a')
insert into A values(2,'b')
insert into A values(3,'C')
insert into A values(4,'d')
insert into A values(5,'e')
insert into A values(6,'f')
go
create trigger tr_a_test on a
after update
as
begin
declare @keyId_old int ,@info1_old varchar(20)
declare @keyId_new int ,@info1_new varchar(20)
---获取修改前的值
select @keyId_old=keyId,@info1_old =info1 from deleted
---获取修改后的值
select @keyId_new=keyId,@info1_new =info1 from inserted
----打印获取的相关值
print '-------修改前的值------'
print @keyId_old
print @info1_old
print '-------修改后的值------'
print @keyId_new
print @info1_new
end
go
update A set info1='testwwwtwt',keyId=108 where keyId =2
go
drop trigger tr_a_test
go
truncate table A
drop table A
go
mybatis
create TRIGGER ${triggerName}
ON ${tableName}
AFTER INSERT ,UPDATE ,DELETE
AS
BEGIN
declare @id varchar(11)
declare @url varchar(255)
declare @object int
declare @responseText varchar(255)
--删除
if(not exists(select 1 from inserted) and exists(select 1 from deleted))
select @id=${titleId} from deleted
ELSE
---获取修改后的值
select @id=${titleId} from inserted
print @id
set @url = 'http://${urlApi}/${controUrl}?id='+@id;
print @url
Exec sp_OACreate 'Msxml2.ServerXMLHTTP.3.0', @Object OUT;
exec sp_OAMethod @object,'open',null,'get',@url,'false'
exec sp_OAMethod @object,'send'
exec sp_OAMethod @object,'responseText',@responseText output
Exec sp_OADestroy @Object
EXEC sp_OAGetErrorInfo @Object --异常输出
END;
现在只要在数据库执行这个sql into demo (name) values ('你真的很棒啊'); 就可以访问接口
这里有个坑啊 如果你的表名是demo,接收java接口的@RequestMapping 里也是叫demo, 那么无论你在怎么增加 它都不会跑到这个方法
嗨!出错了嘛? 看这
SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
借鉴博客:
http://www.manongjc.com/article/44753.html
https://www.jianshu.com/p/244c3cc30123
https://www.cnblogs.com/tohen/p/4265263.html
https://www.cnblogs.com/lflyq/archive/2016/11/15/6065160.html
做个记录...
用数据库推送 websocket接收渲染前端页面应该是 万瑞古德!
-----------------补存-------2020年12月9日11:20:40
之前写的触发器向指定接口传数据,只是写了一个demo,并没有真正使用,后续使用遇到一些问题,做一些记录
问题:
使用mybatis创建触发器和存储过程后,在数据库里添加demo表中的数据,由于传的参数是id,在接口里查询当前参数id的值,结果mybatis查询走到mapper层就卡死了,当前百思不得其解,以为是程序写的有问题。经过不断的摸索和实验最后发现当在数据库中添加
一条数据时触发器立马请求存储过程中的http接口,然后接口根据id查询最新的数据,为啥会卡死呢?原因就是触发器之前,这个事务并未结束,insert并没有真正的添加到数据库中,所以导致一系列问题.
解决:
我的解决思路很简单,上代码
new Thread(() -> {
try {
//放到多线程中等待1-2秒,等他的事务完事后在查询
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
如有问题,请指出