I encountered the following issue (issues really) migrating our application from Hibernate 5 to 6.
Situation:
We have two tables with identical columns, OWNER.TAB_DATA and OWNER.TAB_DATA_STAGING. These are in the schema OWNER.
We connect to the DB as CLIENT and have configured hibernate.default_schema=OWNER. DML privileges to the tables in the OWNER schema have been granted to the CLIENT user.
TAB_DATA_STAGING is populated by a batch job in chunks over the course of multiple transactions. Then, within a new transaction, we move the data over to TAB_DATA with the following HQL:
insertinto TabData(id, col1, col2, col3)
selectmax(id), col1, col2, col3
from TabDataStaging
groupby col1, col2, col3; -- to eliminate possible duplicates in the staging table
Hibernate 5 rendered this HQL into a single DML statement as expected:
Attempts to create a temporary table HTE_OWNER.tab_data. This fails without logging any errors, because HTE_OWNER is not a known schema. Also, even if the schema was correct, it would still fail because CLIENT is not allowed to create tables in the OWNER schema.
Issue our insert statement against the temporary table instead of OWNER.tab_data. This now fails because the temporary table doesn’t exist. Testing this scenario against H2 where everything happens in the same schema and the temporary table could be created, reveals the next step that would have happened:
Copy all rows from the temporary table into the actual target table, OWNER.tab_data.
Question/Issue
Why is an insert into ... select from no longer performed directly? Why the need to copy into a temporary table first and then into the actual target table?
When resolving the names of the temporary tables, Hibernate 6 doesn’t consider that a hibernate.default_schema may have been configured. I found the offending code here and here, the basename and name variables can already be prefixed with the custom schema, which isn’t handled there. The HT_ and HTE_ prefixes are just blindly prepended.