Lock exception while updating a table asynchronously in oracle adf - java

my jdev version :11.1.1.7
In our adf application we have a requirement to upload heavy csv files(10k-100k rows) and process/validate each rows and update in the table with process/validation statuses.
The update is happening for each row by applying the view criteria with a primary key as bind variable and commiting each updated row
All of the above process is happening concurrently using java.util.concurrent utilities.
Everything is working fine but few rows encounter oracle.jbo.JboException: JBO-25014: Another user has changed the row with primary key oracle.jbo.Key[254 ].
I have tried updating the table at the end of the whole executor process and committing all updated rows in batch which works fine but this contradicts one of the requirements as user has to wait till end of the process to see the number of updated records in UI.
My queries :
1.How can i implement a thread safe DB commit operation in ADF in such scenario?
2.Each processed/validated row should be commited to DB so that the updated records can be viewed on UI by user

after your every commit operation use "executequery()" or "closerowset()" for your getviewobject.
eg:public void closemaster() {
this.getMasterView().closeRowSet();
}
or you can use:
public void closemaster() {
this.getMasterView().executeQuery();
}
both answers will work.
i think your problem will be solved.
update what happens.

Related

SAP ASE 16 Sybase Database Duplicate records polling

I am trying to read records from SAP ASE 16 Database table concurrently using java to increase performance. I am using select…..for update query to read database table records concurrently. Here two threads are trying to read records from single table.
I am executing this command on a microservice based environment.
I have done below configuration on database:
• I have enabled select for update using: sp_configure "select for update", 1
• To set locking scheme I have used: alter table poll lock datarows
Table name: poll
This is the query that I am trying to execute:
SQL Query:
SELECT e_id, e_name, e_status FROM poll WHERE (e_status = 'new') FOR UPDATE
UPDATE poll SET e_status = 'polled' WHERE (e_id = #e_id)
Problem:
For some reason I am getting duplicate records on executing above query for majority of records sometimes beyond 200 or 300.
It seems like locks are not being acquired during execution of above command. Is there any configuration that I am missing from database side. Does it have anything to do with shared lock and exclusive lock?

SQLite “after update” trigger in Android does not appear to run after every record update

QUESTION:
What, if anything, could cause an SQLite trigger to only run some of the time?
SUMMARY: I'm getting seemingly inconsistent results from a new trigger I've written in SQLite and I'd like to understand if this is happening because I've made a mistake in my SQL/Java code or if I've possibly encountered a rare scenario where SQL triggers may not work as expected.
DETAILS:
While working on an Android project I have encountered what I originally perceived to be a problem with an SQLite trigger. However, since my new trigger exactly matches several other working triggers in the same project (except for the table names) I am beginning to wonder if my Java code is the issue instead.
The purpose of the trigger I am having trouble with is to monitor changes to TableA, such as the addition of a value in the DismissDateUTC column for example. When an update is made to any data in TableA, the trigger is supposed to put the ID of that updated TableA record into TableAChanges which is later used to determine which records were updated and should be sent back to a web server.
When using the database inspector (in Android Studio v4.2.1) or the program “DB Browser for SQLite” and running an update query on TableA manually, the trigger works exactly as expected and records appear in TableAChanges. When I make updates to TableA programmatically, the trigger does not appear to run. I believe it is not running because no records are written to TableAChanges after updates have been written to TableA.
Things I have tried so far:
Running the app on an Android 7.1.1 device (trigger is NOT working)
Running the app on an Android 8.1.0 device (trigger is NOT working)
Running the app on an Android 11 device (trigger is NOT working)
Running manual update query on TableA from Android Studio DB Inspector (trigger IS working)
Running manual update query on TableA from DB Browser for SQLite (trigger IS working)
Running manual update query on TableA from Android Debug Database by “amitshekhar” (trigger IS working)
The Tables and Trigger SQL:
CREATE TABLE TableA (
ID INTEGER PRIMARY KEY NOT NULL
-- (more table columns) --
, DismissDateUTC TEXT NULL
);
CREATE TABLE TableAChanges (
ID INTEGER PRIMARY KEY NOT NULL
);
CREATE TRIGGER trigTableA_U AFTER UPDATE ON TableA
BEGIN
REPLACE INTO TableAChanges(ID)
SELECT old.ID;
END
The Android Java in the TableA DAO class:
public boolean saveChanges() {
boolean ret = true;
ContentValues cv = new ContentValues();
cv.put("ID", mId);
// (more table columns)
cv.put("DismissDateUtc", mDismissDateUtc);
SQLiteDatabase db = DB.getInstance().getWritableDatabase();
try {
db.replaceOrThrow("TableA", null, cv);
} catch (SQLException e) {
ExceptionDao.logToAcra(e);
ret = false;
} finally {
db.close();
}
return ret;
}
*** In the interest of transparency, I am already aware that I can work around this issue by manually writing records to TableAChanges. However, I still wanted to post this question here because I am hoping to gain an understanding of the cause of this issue rather than ignoring the issue.
The reason that the trigger does not work is because it is an AFTER UPDATE trigger, which means that it will work only after the table is updated.
On the other hand, replaceOrThrow() does not update the table.
It is actually executing an INSERT OR REPLACE INTO... or simply REPLACE INTO... statement which either inserts a new row in the table if the new ID does not already exist in the table, or if it exists, deletes the row that contains the existing ID and inserts the new row.

How to update application cache when a delete operation is committed in Oracle table?

I am having an Oracle table which has my application configurations.I load them at my application startup and use it as my application cache. Now i have requirement to update my configuration if there is any Update in the table. I implemented Oracle's CQN database change notification framework via registering with ROW_ID event. It works for Insert and Update. I get row id in notification and do a lookup in the table using Row id and update my cache. Now while deleting a row, Row id in notification is already deleted from my table then how do i know which configuration to be deleted from cache ? Should i keep row id as key in my cache to do this ? Or any other efficient & safe way to achieve the same.Please suggest. Thanks in advance

How to achieve Multiple Consumer Application for Shared Database (Multitenancy)?

Below Snapshot is current application flow.
Current Flow
When user Logged in at these multiple deployments, then respective SMSAgent(java class) insert user info in database, SMSHelper is a java Scheduler which reads data from database in its local queue,send SMS and then update user status in database.
Issue with this flow
Now,In above scenario, Multiple SMS is getting send to Single User because database is common and both the notification helper takes contact details from database(which may be common) and send SMS to that user.
Existing Solution
Currently, solution to this problem is only available in oracle 11g where select query has for update skip locked support.
Expectation
How to achieve the same with all databases at application level and not at query level ?
First,you have to RESERVE the row by update and then do select.
Suppose u have 200 row,
so first you should do is RESERVE by some value which are unique by instance, also you could limit on no of rows updated in your query and then select the row which are reserved by your query
UPDATE TABLE_NAME SET SERVER_INSTACE_ID=UNIQUE_VAL AND ROWNUM <= RECORD_RESERVATION_LIMIT
SELECT * FROM TABLE_NAME WHERE SERVER_INSTANCE_ID=UNIQUE_VAL
Through this approach, you don't need to obtain lock on row or table.

How to poll database and trace the latest record using java?

I have a situation where user upload a new file when file successful submitted then one records is inserted into database table.i will run other class,that poll database if new records is inserted retrieve file name then read file and insert all file records into database table.i'm not getting any idea to sortout this problem,please help me and provide your views for this situation.
Thanks
Well , it seems that you want to have a Java class that will periodically check a table (say TableA) and process those new records that are inserted since last checking time.
You should at least have a column (eg ,polled_time) to capture if a record is polled before or not . polled_time is the timestamp when the record is last polled . It is null if the record is never polled before.
Whenever the Java class starts ,it should select the records that are not polled for process (select * from TableA where polled_time is null) . After process each record , you should update the polled_time to indicate it is polled and avoid it is selected out again to process when the Java class runs next time ( update TableA set polled_time = now() where id= xxxxx).
Finally, you have to setup a schedule task ( For Window platform) / a cron job (For Linux / Unix platform) to run this java class periodically ,
Why can't you perform both operations on the same servlet doPost()? Or get rid of the Filename table and just have the contents table and avoid the whole polling situation?
doPost(...) {
try {
validateFile(...);
updateFileTable(...);
updateFilenameTable(...);
} catch (...) {...} finally {...}

Categories