Hi everyone! Have a tough one here. I'll try and explain with all needed info, but If you need some additional data just let me know.
I have a stored procedure that is returning a resultSet ( mysql ). Basically what i'm doing is pivoting the columns from the cursor to a temp table. So I don't know what columns the table will have until after the stored proc is run:
DELIMITER $$ DROP PROCEDURE IF EXISTS my_report $$
CREATE PROCEDURE my_report( IN userfilterClause VARCHAR(64) , IN eventCodefilterClause VARCHAR(64) , IN startMonth INT , IN startYear INT , IN endMonth INT , IN endYear INT ) BEGIN DECLARE dgsUser_whereClause VARCHAR(64) ; DECLARE eventCode_whereClause VARCHAR(64) ; DECLARE done INT; DECLARE v_dgsUser, v_eventCode, lastUser, lastEvent VARCHAR(64); DECLARE v_month, v_date VARCHAR(20); DECLARE v_year VARCHAR(4); DECLARE v_total INT; DECLARE firstPass INT DEFAULT 1; DECLARE tbl_name VARCHAR(64); DECLARE colCount INT; DECLARE tempTblRows INT;
DECLARE cur1 CURSOR FOR SELECT dgsUser, eventCode, concat( monthname(submitTime) , '_' , year(submitTime) ), count(dgsUser) FROM drmJobs WHERE submitTime IS NOT null AND dgsUser like userFilterClause AND eventCode like eventCodeFilterClause AND ( year(submitTime) >= startYear AND month(submitTime) >= startMonth ) AND ( year(submitTime) <= endYear AND month(submitTime) <= endMonth )
GROUP BY dgsUser, eventCode, year(submitTime), monthname(submitTime) ORDER BY dgsUser, year(submitTime), monthname(submitTime) DESC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE; DECLARE CONTINUE HANDLER FOR SQLSTATE '42S21' SET @cont=1;
DROP TABLE IF EXISTS test_data; CREATE TEMPORARY TABLE test_data ( `dgs_user` varchar(64) NOT NULL, `event_code` varchar(64) default NULL );
OPEN cur1;
loopy: LOOP FETCH cur1 INTO v_dgsUser, v_eventCode, v_date, v_total;
IF `done`THEN LEAVE loopy; END IF; IF firstPass = 1 THEN INSERT INTO test_data(dgs_user, event_code) values (v_dgsUser, v_eventCode); SET firstPass = 0; ELSE IF lastUser != v_dgsUser OR lastEvent != v_eventCode THEN INSERT INTO test_data(dgs_user, event_code) values (v_dgsUser, v_eventCode); END IF; END IF;
SET lastUser = v_dgsUser; SET lastEvent = v_eventCode;
SET @pivot_col := CONCAT('ALTER TABLE test_data ADD COLUMN ', v_date, ' VARCHAR(64)'); PREPARE alt_table FROM @pivot_col; EXECUTE alt_table;
DEALLOCATE PREPARE alt_table; SET @build_update := CONCAT( 'UPDATE test_data SET ', v_date , ' = ' , v_total , ' WHERE dgs_user = ' , '\'', v_dgsUser, '\'', ' AND event_code = ' , '\'', v_eventCode, '\'' );
PREPARE cust_update FROM @build_update; EXECUTE cust_update ; DEALLOCATE PREPARE cust_update;
END LOOP loopy;
CLOSE cur1;
SELECT * FROM test_data; END $$ DELIMITER ;
For this reason I'm not using a hibernate named query, and instead i'm doing a session.connection(). and then: CallableStatement cs = con.prepareCall("{CALL jobSummaryReport(?,?, ?,?, ?,? ) }");
Since I don't know the columns coming back and they are non mapped columns anyway its too difficult to use hibernate to run this query. I would be open to suggestions though, if it is possible to do so using the hibernate named query.
So here's what happens. I have a report that when I execute the first time it runs fine. But if I run again giving different filter values ( for example a different first name ) then I get an error stating a column doesn't exist.
The trick is if I execute the stored proc again ( basically recompliling it ) that new query will work. As long as I do that after each time I click 'go' on the report everything works. I can also make things work by manually killing the mysql connection.
I need hibernate to completely release / kill the connection, but it doesn't seem to. If it did the stored proc would go out of scope and stop holding on to whatever its holding on to.
I am doing cs.close(), and session.close(); at the end of the method.
|