-
Notifications
You must be signed in to change notification settings - Fork 38.5k
INSERT SELECT of large CLOB causes ORA-01461 on setString [SPR-12240] #16854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Juergen Hoeller commented Oracle's 4000 character limit is well known but a very Oracle-specific pain. The workaround of using setClob works on Oracle but not necessarily on other databases... Have you tried Oracle's "SetBigStringTryClob" setting yet? This is supposed to allow for the use of setString with larger values. Note that Spring's JDBC template and operation APIs have variants which accept a user-provided We also have support for a Juergen |
Anthony Yeracars commented SetBigStringTryClob doesn't work with Oracle 11 drivers, it turns out. (As per http://stackoverflow.com/questions/7817860/does-the-oracle-jdbc-driver-setbigstringtryclob-property-still-work; and I verified it.) I'm a little surprised setClob() doesn't work on all data managers since it's part of the interface, but I will certainly accept your word. That said, I observe other data-manager-specific code in StatementCreatorUtils. I had dismissed PreparedStatementSetter while inspecting the code, because SqlUpdate never calls its internal newPreparedStatementSetter() method in this test case, and also does not use the JdbcTemplate.update() method that accepts a PreparedStatementSetter (when I call update(Object ... params)). I have created a workaround that takes advantage of PreparedStatementSetter, although threading it into SqlUpdate is onerous (and fragile). |
Juergen Hoeller commented According to that StackOverflow link, setString does work for CLOBs out of the box on Oracle 11, without a need for setting a specific connection property anymore? That seems to suggest that Spring's current use of setString is fine, or am I missing something? Juergen |
Anthony Yeracars commented Please examine and run my test case which demonstrates conclusively that setString() does not work for INSERT ... SELECT ... FROM DUAL, but does work for INSERT ... VALUES, for CLOBs > 4000. I tried very hard to give you complete documentation and a simple test case. Separately I disagree with your characterization that this should be considered as other than a bug. Oracle clearly documents their interface, which is consistent with the observed behavior. Again, all references can be found in my comments and in the test case itself. |
Juergen Hoeller commented I don't mean to deemphasize your test case. I'm just trying to check the situation against the latest Oracle documentation, and this is what the link given on StackOverflow says: "The setString, setCharacterStream, and setAsciiStream methods use direct binding for data smaller than 32767 bytes in the database character set." In that context, it's documented that the former "SetBigStringTryClob" connection property isn't needed anymore because the driver automatically chooses LOB bindings now. This is how Oracle currently documents their drivers in version 11, and this suggests that the 4000 character limit doesn't apply anymore? Seriously, am I missing something? Juergen |
Juergen Hoeller commented There is a documented size limit for In terms of potential changes to Spring's Juergen |
Anthony Yeracars commented So, I didn't try values as large as 32K!!! The oracle doc for setString() says it will convert the string a VARCHAR or LONGVARCHAR (the latter presumably/apparently when > 4000 bytes); it does not discuss "LOB binding". My (wild) guess is that "LOB binding" refers to the mechanism by which the driver sends the data to the data manager, and not to the datatype that the driver/data manager applies to the parameter. It appears to me that the only way the driver has of understanding the parameter datatype is via which set<type>() call you make; I would say it's not unreasonable for Oracle to say the choices are limited VARCHAR and LONGVARCHAR but not CLOB. I do admit, by the way, that it is not wholly unreasonable to call this an Oracle bug, but since, from their perspective it is likely they would say the "correct behavior"/"easy workaround" is to use setClob(), it makes more sense to call this a Spring bug. As I said I now have a klunky/fragile workaround using PreparedStatementSetter: it would (also) be nice if SqlUpdate exposed a (non-final) protected method to generated a PreparedStatementSetter, and actually used it (at least my workaround would be much less fragile). |
Juergen Hoeller commented Alright, as of 4.1.1, This should be fine for other drivers/databases as well since it uses standard JDBC 4.0 API, with some defensiveness added through the length 4000 check (i.e. to keep using We have quite a few related JDBC refinements in 4.1 GA and 4.1.1, so this is a good fit timing-wise. However, due to the changes in interaction with the JDBC driver abstraction and due to this being a vendor/driver-specific problem, it does not suggest itself as a backport candidate. This will be available in the upcoming 4.1.1 snapshot. Would be great if you could give it a try before the 4.1.1 release on Tuesday... Juergen P.S.: As for |
Anthony Yeracars commented Thank you. Unfortunately we're still running 3.1.0, so I'll have to stick with my JdbcTemplate hack, but that also means I won't have an opportunity to give your fix a proper try-out. |
Anthony Yeracars opened SPR-12240 and commented
Affects: 4.1 GA
Attachments:
Issue Links:
Referenced from: commits 3908804
The text was updated successfully, but these errors were encountered: