Spring Boot how execute stored procedure multiple times? - spring

I need to execute a procedure multiple times with the requestbody. For now, i am using for loop to do that, but it is not a good way. For example, when the one request is failed, catching that request is a problem. See for the example usage.
Implementation of stored procedure with for-loop;
**Controller**
public void runSP(
#RequestBody List<IdNoteModel> idNotes
){
getService().runSP(idNotes);
}
**Service**
public void runSP(List<IdNoteModel> idNotes){
for (IdNoteModel idNote : idNotes){
getRepository().runSP(idNote);
}
}
**Repository**
#Query(nativeQuery = true, value = "EXECUTE PROCEDURE SP_RUN_ID_NOTE(:id, :note)")
void runSP(Long id, String note);
Is there a better way to run stored procedures multiple times? or do you have an idea to catch the failed requests?

You can use one stored procedure in which you can use the cursor to execute the procedure (SP_RUN_ID_NOTE) multiple times. In that stored procedure, you can also use rollback for something to fail. In your above case, you can store request body input in the table and then call procedure while taking input row from that table.

You can use #Retryable for this purpose and also you can catch exceptions and log requests with #Recover

Related

How to call stored procedure that returns a JSON using Spring JPA

I have a stored procedure that returns a JSON instead of usual table. How do I call it using spring JPA? When I called like normal stored procedure it says
SQL Error: 0, SQLState: S1093
Parameter out was not defined for stored procedure
the way I called the stored procedure is
public interface ITransactionserviceJPA extends JpaRepository<CategoryEntity, Integer>{
#Procedure(procedureName = "getApprovalRequests")
String getApprovalRequests(String EmpId);
}
I checked the stored procedure. It did not have any out parameter. But it returns JSON object so I cannot use use void instead of String. But when I use String as return type it gives error. I searched for few hours but I couldn't find any solution. Idk even this is possible or not.

JDBC Batch insert exception handling to know the particular failed record

I want to read a txt file which has oracle insert statements in java program and execute as a batch, If any of the record gets failed in the batch, How do i get to know the particular insert statement only got failed.
for Ex.if i have 1000 records in file and 659 record gets failed in insertion,
how can i get to know the 659 record got failed in executebatch update.Is there any other process to do this please let me know.
There are two ways to handle the above situation either you check-in Java code or write the procedure
Java Code: this will either load everything or roll back the whole batch.
updateResult = preparedStatement.executeBatch();
checkSuccessfulUpdates(updateResult);
public static void checkSuccessfulUpdates(int[] updateCounts) throws Exception {
for (int i :updateCounts) {
if (i == Statement.EXECUTE_FAILED) {
throw new Exception("Not all rows were updated. Rolling back entire batch ");
}
}
}
Write a SQL procedure
Send the entire data in custom object to procedure, load it 1 by 1 by record, handle the exception within the loop, on error load the failed record in a temporary table.

Salesforce bulkify code - is this not already bulkified?

We have a class in salesforce that is called form a trigger. When using Apex Data Loader this trigger throws an error oppafterupdate: System.LimitException: Too many SOQL queries: 101
I commented out a line of code that calls the following static method in a class we wrote and there are no more errors with respect to the governing limit. So I can verify the method below is the culprit.
I'm new to this, but I know that Apex code should be bulkified, and DML (and SOQL) statements should not be used inside of loops. What you want to do is put objects in a collection and use DML statements against the collection.
So I modified the method below; I declared a list, I added Task objects to the list, and I ran a DML statement on the list. I commented out the update statement inside the loop.
//close all tasks linked to an opty or lead
public static void closeTasks(string sId) {
List<Task> TasksToUpdate = new List<Task>{}; //added this
List<Task> t = [SELECT Id, Status, WhatId from Task WHERE WhatId =: sId]; //opty
if (t.isEmpty()==false) {
for (Task c: t) {
c.Status = 'Completed';
TasksToUpdate.add(c); //added this
//update c;
}
}
update TasksToUpdate; //Added this
}
Why am I still getting the above error when I run the code in our sandbox? I thought I took care of this issue but apparently there is something else here? Please help.. I need to be pointed in the right direction.
Thanks in advance for your assistance
You have "fixed" the update part but the code still fails on the too many SELECTs.
We would need to see your trigger's code but it seems to me you're calling your function in a loop in that trigger. So if say 200 Opportunities are updated, your function is called 200 times and in the function's body you have 1 SOQL... Call it more than 100 times and boom, headshot.
Try to modify the function to pass a collection of Ids:
Set<Id> ids = trigger.newMap().keyset();
betterCloseTasks(ids);
And the improved function could look like this:
public static void betterCloseTasks(Set<Id> ids){
List<Task> tasksToClose = [SELECT Id
FROM Task
WHERE WhatId IN :ids AND Status != 'Completed'];
if(!tasksToClose.isEmpty()){
for(Task t : tasksToClose){
t.Status = 'Completed';
}
update tasksToClose;
}
}
Now you have 1 SOQL and 1 update operation no matter whether you update 1 or hundreds of opportunities. It can still fail on some other limits like max 10000 updated records in one transaction but that's a battle for another day ;)

Will Entity Framework and SQL Server lock a object/record while deleting it

I am deleting some objects and rows using two methods inside my asp.net MVC web application: first approach includes deleting an Entity Framework object, such as:
public void DeleteMyObject(MyObject a)
{
entities1.MyObject.Remove(a);
}
while the second approach is calling a stored procedure from my repository method to delete a database row such as:
public void Deleteuserclass(string a, int u)
{
entities1.deleteuserclass(a, u);
}
which calls the following stored procedure:
ALTER PROCEDURE dbo.deleteuserclass
#userid nvarchar(50),
#classid int
AS
Begin
Delete from Users_Classes where UserID = #userid AND ClassID = #classid
if ##rowcount = 0
Raiserror('No record deleted',1,16)
END
Using any of the above two approaches; can I be confident that if two delete requests for deleting the same object arrive at the server at the same time, then only one request will delete the record from the database and the other request will receive an exception (I mean will the Entity Framework or the SQL Server database lock the row while it is being deleted ?)?
BR
One or the other will execute first.
If your stored procedure is execured second you will get an exception due to the if statement in the stored procedure.
If the EF command is executed second there will be a OptimisticConcurrencyException, see: EF eqivalent for rows affected of SqlCommand.ExecuteNonQuery

hsqldb not showing reflection of insert query while runing with JUnit test

i am using hsqldb as database. i create LmexPostParamDao which has a method insertLmexPostParam(NameValuePostParamVO nameValuePostParamVO) which will insert data in databse. for testing this method i used JUnit test to insert some data in hsqldb.
my JUnit test method is as below:
#Test
public void testInsertLmexPostParam(){
String lmexPostParamId = UUID.randomUUID().toString();
NameValuePostParamVO nameValuePostParamVO = new NameValuePostParamVO();
nameValuePostParamVO.setLmexPostParamId(lmexPostParamId);
nameValuePostParamVO.setParamName("adapter_id");
nameValuePostParamVO.setParamValue("7");
lmexPostParamDao.insertLmexPostParam(nameValuePostParamVO);
}
my insert method is as below:
#Override
public void insertLmexPostParam(NameValuePostParamVO nameValuePostParamVO) {
String insertQuery = "insert into LMEX_POST_PARAM(lmex_post_param_id, param_name, param_value) values (?,?,?)";
String[] paramArr = { nameValuePostParamVO.getLmexPostParamId(), nameValuePostParamVO.getParamName(), nameValuePostParamVO.getParamValue()};
int update = adapterJdbcTemplate.update(insertQuery, paramArr);
System.out.println(update);
}
when i run my test case it's returning me 1 as output which is result of adapterJdbcTemplate. which means data inserted sucessfully. but when i see my database it is not showing me a that row which inserted. and when i debug my testcase method with same values it's give a exception : Data integrity violation exception. and after this exception when i see my database it's showing that row in my database. what will be the problem. i do not. when i see code it's look like everything is fine. help me to resolve this.
Thank you
Check your CREATE TABLE statement for LMEX_POST_PARAM. The CHAR and VARCHAR types must be defined as CHAR(N) and VARCHAR(N), with N large enough to accept the values that you insert. For example, VARCHAR(100).
If your problem is the database is not showing the successful insert, then you should create your database with WRITE_DELAY = 0 or false. See the HSQLDB documentation for the version you are using.

Resources