Mybatis Oracle Stored Procedure - oracle

I am having problem calling oracle Stored Procedure and getting Output parameters from Oracle Stored Procedure.
Here is my mapper
AppUserMapper.java
public interface AppUserMapper {
#Select(value= "{ CALL sp_check_user( #{userId, mode=IN, jdbcType=VARCHAR }, #{userPwd, mode=IN, jdbcType=VARCHAR}, #{userType, jdbcType=VARCHAR, mode=OUT} )}")
#Options(statementType = StatementType.CALLABLE)
Object getUserType(String userId,String UserPwd);
}
Dao call
Map<String, Object> retrurnStatus = (Map<String, Object>) appUserMapper.getUserType(userId,UserPwd);
Here is Stored Procedure code
CREATE OR REPLACE PROCEDURE HR.sp_check_user (userId VARCHAR,userPwd VARCHAR, userType OUT VARCHAR )
AS
BEGIN
BEGIN
select user_type into userType from appuser where USER_ID = userId and USER_PWD = userPwd ;
EXCEPTION
WHEN NO_DATA_FOUND THEN
userType := 'Invalid';
END ;
END ;
/
It is executing stored procedure but giving error
DEBUG 2014-04-12 09:51:56,948 org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl: ==> Preparing: { CALL sp_check_user( ?, ?, ? ) }
DEBUG 2014-04-12 09:51:57,103 org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl: ==> Parameters: abc(String), abc1(String)
Could not complete request
java.lang.NullPointerException
at com.appuser.dao.AppUserDaoImpl.getUserType(AppUserDaoImpl.java:33)
I had been trying multiple options but could not find sample which I can take as is and try.
I will relay appropriate help on this as I have been trying to use oracle stored procs in mybatis with multiple input and output parameters.
Can someone provide simple example for calling Oracle stored procedure using mybatis for multiple input output parameters?

Jeff Butler says in mybatis-user group:
For stored procedure parameters, MyBatis will map both input and
output parameters to properties in the parameterType.
You can try sending a Map, POJO or three annotated variables having userId, userPwd and userType. After the SP is called, MyBatis will set the OUT parameter to userType.
I cannot try it now, I'll try to edit the answer later. But can you try these,
1) Define your function as follows, and check if userType is updated after you call the SP.
void getUserType(Param("userId") String userId, Param("userPwd") String userPwd, Param("userType") String userType);
or
2) Create a Map, add 3 key-value pairs, i.e. ("userId", 1234), ("userPwd", 666), ("userType, null) tuples. After you call the SP, you can try getting the userType value.
void getUserType(Map<String, Object> myMap);
or
3) Create a class with 3 variables (userId, userPwd, userType), getters, setters. Set userId and userPwd values. Call the SP. Then, userObj.getUserType().
void getUserType(UserClass userObj);

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.

Spring Boot how execute stored procedure multiple times?

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

Slick/Oracle PLAIN SQL Get auto generated ID after insert

I am trying to run a query via Slick in Scala that will insert a record into an Oracle db and return the auto generated ID as the result. I see that this is possible using Slick's syntax but is this possible using a plain SQL query? With below code I can only get a return value of -1.
val name = "Bob"
db.run(sql"""DECLARE NEW_PERSON_ID;
BEGIN
INSERT INTO TB_PEOPLE (ID, NAME)
VALUES(SEQ_PEOPLE.NEXTVAL, $name)
RETURNING ID INTO NEW_PERSON_ID;
END;""".as[Int])
It seems that Slick doesn't support output parameters so using Oracle's returning syntax won't work. A workaround I found is to first generate an ID and then insert using that ID (requires 2 queries). The queries are wrapped in a transaction.
val name = "Bob"
val action = for {
newPersonId <- sql"""SELECT SEQ_PEOPLE.NEXTVAL FROM DUAL""".as[Int]
_ <- sqlu"""INSERT INTO TB_PEOPLE (ID, NAME) VALUES ($newPersonId, $name)"""
}
db.run(action.transactionally)

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