I created a stored procedure in MySQL and called it from a Java application with JPA EclipseLink. Once the procedure is called, it has a "sleep(sec)" method inside, and then it executes something successfully unless the application is turned off, it seems like the procedure is canceled too which is not what I want. The same thing I tried using JDBC PreparedStatements, the same result. Is there any workaround to make the stored procedure work even if the app was shut down after the procedure call.
Stored Procedure
DELIMITER //
DROP PROCEDURE IF EXISTS session_procedure//
CREATE PROCEDURE session_procedure
(
IN userID INT
)
BEGIN
SELECT SLEEP(30);
UPDATE users
SET users.Active = 0
WHERE users.Id = userID;
END//
DELIMITER ;
Procedure call in Java
public static void destroySessionCountdown(EntityManager entityManager, Account akk){
int accountId = akk.getId();
StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("session_procedure");
storedProcedure.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN);
storedProcedure.setParameter(1, accountId);
try {
storedProcedure.execute();
}catch(Exception e){
e.printStackTrace();
}
// force logout
}
I suppose that when you closed connection to the DB, all processes related to it were cancelled including the running call of this stored procedure. I don't think you can avoid it.
What you are trying to implement is a kind of scheduled job. I would suggest to use cron instead. For the procedure you shown a simple SQL instead of stored procedure would be sufficient. The logic related to delays and to the execution time could be placed to a shell script and to the cron.
Related
Use Case:
I have the procedure stored in the database:
CREATE DEFINER=`DEVDBA`#`%` PROCEDURE `TestReporting`()
begin
truncate table `report_controller_total_request`;
insert into `report_controller_total_request`
select count(*) as total_no_of_requests from log_request;
end
*** Now I want to call this stored procedure from the code base using EntityManager
public void UpdateServer() {
System.out.println("Update Server Start");
EntityManager entityManager = null;
entityManager = EntityManagerFactoryBuilder.createEntityManager();
entityManager.getTransaction().begin();
StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("TestReporting");
boolean isExceuted = storedProcedure.execute();
System.out.println("Update Server Done: "+isExceuted);
entityManager.getTransaction().commit();
entityManager.close();
}
I have tried different versions of the code, this is the last I tried before posting.
I'm not able to call the procedure, it gives me some error every time
Update Server Start
Update Server Done: false
Summary:
I already have the procedure stored in the database, I want the java code using EntityManagger to call the procedure, which in turn updates the database table.
Note: I'm using JNDI for the database connection.
I have the following stored procedure in mysql
DELIMITER $$
CREATE DEFINER=`user`#`%` PROCEDURE `sp_getJobs`()
BEGIN
SELECT * FROM jobs_table;
END$$
DELIMITER ;
and the following defined in hsqldb (for unit tests)
CREATE PROCEDURE sp_getJobs() READS SQL DATA
DYNAMIC RESULT SETS 1
BEGIN ATOMIC
DECLARE result CURSOR WITH RETURN FOR SELECT * FROM jobs_table FOR READ ONLY;
OPEN result;
END
Spring framework code that executes stored procedure
query = "Call sp_getJobs"; //This is used when MySql is database
query = "Call sp_getJobs()"; //This is used when HsqlDb is used in testing
getJdbcTemplate().query(query, rs -> {
process(rs);
return null;
});
private void process(ResultSet rs) {
while (rs.next()) {
//do something
}
}
The spring code that executes mysql works fine, however, when I execute the same code against hsqldb I get an empty result set (rs.next() returns false).
Note - The createdata.sql file that I use for testing, creates the jobs_table and populates it with 6 rows of data too. So the table should have data.
The Spring code doesn't look right for HSQLDB procedures. It will probably work for a function that returns a table.
Change the procedure to FUNCTION and return a table containing the data.
Alternatively, use the procedure but after calling it, execute getMoreResults() prior to process(ResultSet rs) call.
While the code below didnt work for only hsqldb stored procedure listed in question
getJdbcTemplate().query(query, rs -> {
process(rs);
return null;
});
private void process(ResultSet rs) {
while (rs.next()) {
//do something
}
}
code below worked for all of them - mysql, sqlserver, informix & also hsqldb
SimpleJdbcCall simpleJdbcCall =
new SimpleJdbcCall(getJdbcTemplate().getDataSource())
.withCatalogName(catalog)
.withProcedureName(query);
where catalog is the package name. So, if your stored procedure is such as accounts.get_all_expired_accounts then catalog="accounts" & query="get_all_expired_accounts".
I have a stored procedure in a postgres database. I'm using the postgres JDBC driver to execute a stored procedure, and I do not care about the return type, and can't execute the query. It's indicating that there's a syntax error near the name of the function.
In procedures that return rows, I've been able to do this via a PreparedStatement and setting the parameters, like:
PreparedStatement prepared = connection.prepareStatement("SELECT * FROM NonQueryProcedure(?)");
prepared.setInt(1, 999);
// ....
ResulSet resultSet = prepared.executeQuery();
However, I can't seem to get this to work for an "update" stored procedure where I don't care about the return type. I've tried using connection.prepareStatement() and prepareCall(), and also tried executing it with statement.execute(), .executeUpdate(), and .executeQuery(), without success.
How can I execute a stored procedure where I don't care about the return type?
As PostgreSQL has no "real" procedures, functions are simply executed using a SELECT statement:
statement.execute("select NonQueryProcedure(?)");
Note that inside a PL/pgSQL function, you can use the perform statement to call such a function. But this is not available outside of a PL/pgSQL block.
Without the actual syntax error, I can't say for sure, but try this:
"SELECT * FROM \"getData\"(?)"
CamelCase/PascalCase is a BAD idea in any SQL database. Either it folds it to a single case and all you see is AMASSOFUNREADABLELETTERS or it requires quoting and you will have to forevermore type "aMassofLettersAndQuotesAndShiftKeysAndMyFingersHurt" anytime you want to avoid a syntax error.
I'm calling a db2 stored procedure(p1) from java.
This procedure makes some inserts on a table, that has a trigger after insert. The trigger calls another procedure(p2), that raises an exception 'SIGNAL SQLSTATE '50000' SET MESSAGE_TEXT = 'An error';
My called db2 procedure runs successfully, I should no get an SQLException in java caller. but I java code, I receive the sqlexception as if procedure p1 has raised it.
Why db2 acts like this and how can I prevent it?
Later edit
Another thing could happen.
Something could be broken in db internal kitchen on that database, so when i call procedure db2 actually executes procedure p2.
Unfortunately i don't have access to system where problem occurred so i can only ques what happened.
What do you think, which scenario is more plausible?
Are you sure that it is a trigger and the second procedure is run as a separate task?
I suppose your procedure code is something like this:
procedure1()
begin
//do smth
result = procedure2();
//do smth else
end
That's why you get the exception.
I have a prepared statement call in java that calls a procedure that commits or rolls back a sybase transaction. Is there anyway I can check from my java calls the result of that transaction, ie. success for commit or failure for rollback?
Alternatively, I want to check that the procedure completed without errors - whats the best way of doing that?
Thanks
If the rollback or commit happens within the stored procedure, then the only way to know the success is to have the stored procedure return its success status. Then, Java will have access to this result.
A stored procedure should return some kind of status or error code.
Put that in an OUT parameter and read that from the proc.
//Calling a stored procedure which takes in 2 parameters for addition
/*
--EXECUTE ADDITION 10,25,NULL
ALTER PROCEDURE ADDITION
#A INT
, #B INT
, #C INT OUT
AS
SELECT #C = #A + #B
*/
CallableStatement cs2 = con.prepareCall("{call ADDITION(?,?,?)}");
cs2.registerOutParameter(3,java.sql.Types.INTEGER);
cs2.setInt(1,10);
cs2.setInt(2,25);
cs2.execute();
int res = cs2.getInt(3);
System.out.println(res);
I think you're using the wrong approach. The client (the JAVA code in this case) should be committing or rolling back, not the sybase stored procedure. I assume here that by "calling a procedure" you mean a stored procedure that commits or rolls back.
If you use the approach I just mentioned, then you can put everything in a try/catch block and handle the commit/rollback accordingly.
try {
PreparedStatement ps = create prepared statement;
ps.execute();
// nothing went wrong, commit
} catch (SqlException e) {
// something wen't wrong, rollback
}
If by "calling a procedure" you mean just another JAVA method, then the I don't know why you would have a separate method to do a commit or rollback, you can handle it all in the try/catch block as shown above.