sql-serverdatabasetomcatquery-notifications

How to push the data from database to application?


I want to push the data from database to application instead of application pull the data. I have installed ms sql server and apache tomcat server. I have my application in apache tomcat, here I made connection to database. Now I want database send the data whenever there is update in data. But all I know is fetch the data from database is not good idea, because application needs to monitor the database for updated data will lead to fire the query for every 5 sec, this is not efficient as well.

I google it I got some answers they are Query Notification here, Sql server Agent Job to schedule the task automatically. If you have any other suggestion please post it.


Solution

  • There surely are several possibilities to do that:

    You can read a little about them in this discussion: Serial numbers, created and modified in SQL Server.

    Personally I would prefer Query Notification over other methods, because it already has support fopr various cases (e.g. sync/async communication) and you don't have to reinvent the wheel. And is in your case recommended by Microsoft.

    Polling is another method you've mentioned. It's is a more like traditional method and there can be some performance penalties related, but you shouldn't worry about them if you are careful enough. For example, if you already have an authentication built in your application, you can create another column in your Users table that is set if there are any changes related to that user. And then, there can be just a thread in your app that will perform a query every second against this table (even dirty reads with NOLOCK shouldn't be a problem here) and maintain some in-memory structure (e.g. thread-safe dictionary) that says which client should get pushed. Another thread polls your dictionary and when it finds there something for the client, performs a db query that extracts data and sends it to the client. This looks like a lot of unnccessary work, but at the end you get two independent workers which somewhat helps to separate concerns; first one is just an informer which performs 'lightweight' database polling; second one extract real data and performs server push. You can even optimize the push-worker in the way that when it runs, it checks if multiple clients need some data and then executes the select for all of those who need it. You would probably want the second worker to run less frequently than first one.

    EDIT

    If you wish to use non-.NET technology to achieve the same functionality, you will have to get more into SQL Server Service Broker. Query Notification is a simplified layer built in .NET on top of SQL Server Service Broker, and you would have to build at least part of that layer by yourself. This includes creating queue, message type, service and stored procedures with SEND and RECEIVE on the other side. You will have to take care of the conversation/dialog by yourself. SB is actually a async-messaging world adjusted to work in RDBMS environment, so you will see some new TSQL expressions. However, MSDN is here to help:

    This could help as well: Externally activate non-.NET application from Service Broker

    Example on how to code the stuff:

    -- First you have to enable SB for your database
    USE master
    ALTER DATABASE Playground
    SET ENABLE_BROKER
    GO
    
    USE Playground
    GO
    
    -- Then create a message type; usually it will be XML
    -- because it's very easy to serialize/deserialize it
    CREATE MESSAGE TYPE [//Playground/YourMessageType]
    VALIDATION = WELL_FORMED_XML
    GO
    
    -- Then create a contract to have a rule for communication
    -- Specifies who sends which message type
    CREATE CONTRACT [//Playground/YourContract] (
        [//Playground/YourMessageType] SENT BY ANY)
    GO
    
    --Creates queues, one for initiator (1) and one for target (2)
    CREATE QUEUE MyQueue1
    GO
    CREATE QUEUE MyQueue2
    GO
    
    -- Finally, configure services that 'consume' queues
    CREATE SERVICE [//Playground/YourService1]
    ON QUEUE MyQueue1 ([//Playground/YourContract])
    GO
    
    CREATE SERVICE [//Playground/YourService2] 
    ON QUEUE MyQueue2 ([//Playground/YourContract])
    GO
    
    -- Now you can send a message from service to service using contract
    DECLARE 
        @dHandle uniqueidentifier,
        @Msg nvarchar(max) 
    
    BEGIN DIALOG @dHandle
        FROM SERVICE [//Playground/YourService1]
        TO SERVICE '//Playground/YourService2'
        ON CONTRACT [//Playground/YourContract]
    WITH ENCRYPTION = OFF
    
    SELECT @Msg = (
        SELECT TOP 3 *
        FROM Table1
        FOR XML PATH('row'), ROOT('Table1'))
    
    ;SEND ON CONVERSATION @dHandle 
    MESSAGE TYPE [//Playground/YourMessageType] (@Msg)
    
    PRINT @Msg
    GO
    
    -- To get the message on the other end, use RECEIVE
    -- Execute this in another query window
    DECLARE @dHandle uniqueidentifier
    DECLARE @MsgType nvarchar(128)
    DECLARE @Msg nvarchar(max)
    
    ;RECEIVE TOP(1)
        @dHandle = conversation_handle,
        @Msg = message_body,
        @MsgType = message_type_name
    FROM MyQueue2
    
    SELECT @MsgType 
    SELECT @Msg
    
    END CONVERSATION @dHandle 
    GO