[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-5704) New getSubString() handling in ClobProxy is incompatible with MySQL JDBC PS.setClob(int, Clob) for empty CLOB

Tom Waterhouse (JIRA) noreply at atlassian.com
Mon Jan 17 18:45:06 EST 2011


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-5704?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=39670#action_39670 ] 

Tom Waterhouse commented on HHH-5704:
-------------------------------------

I just updated to hibernate-core 3.6.1-SNAPSHOT and receive the same error:

Caused by: java.sql.SQLException: Start position [1] cannot exceed overall CLOB length [0]
	at org.hibernate.engine.jdbc.ClobProxy.invoke(ClobProxy.java:146)
	at $Proxy226.getSubString(Unknown Source)
	at com.mysql.jdbc.PreparedStatement.setClob(PreparedStatement.java:3553)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at bitronix.tm.resource.jdbc.BaseProxyHandlerClass.invoke(BaseProxyHandlerClass.java:63)
	at $Proxy184.setClob(Unknown Source)
	at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$1.doBind(ClobTypeDescriptor.java:60)
	at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:89)
	at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:282)
	at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:277)
	at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:85)
	at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2166)
	at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2143)
	at org.hibernate.persister.entity.AbstractEntityPersister$4.bindValues(AbstractEntityPersister.java:2321)
	at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:56)
	... 129 more
[2011-01-17 03:41:58.568, 70659]DEBUG[http-8080-1](ActiveUserFilter.java:103) - ActiveUserFilter.doFilter()


> New getSubString() handling in ClobProxy is incompatible with MySQL JDBC PS.setClob(int, Clob) for empty CLOB
> -------------------------------------------------------------------------------------------------------------
>
>                 Key: HHH-5704
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5704
>             Project: Hibernate Core
>          Issue Type: Bug
>    Affects Versions: 3.6.0
>         Environment: MySQL JDBC 5.1.12 / 5.1.13
>            Reporter: Sergey Vladimirov
>             Fix For: 3.6.1, 4.0.0.Alpha1
>
>         Attachments: hibernate-3.6.0-HHH-5704.patch
>
>
> For all empty but not-null CLOBs MySQL drivers do the following (com.mysql.jdbc.PreparedStatement):
> 			String forcedEncoding = this.connection.getClobCharacterEncoding();
> 			
> 			if (forcedEncoding == null) {
> 				setString(i, x.getSubString(1L, (int) x.length()));
> 			} else {
> 				try {
> 					setBytes(i, x.getSubString(1L, 
> 							(int)x.length()).getBytes(forcedEncoding));
> 				} catch (UnsupportedEncodingException uee) {
> 					throw SQLError.createSQLException("Unsupported character encoding " + 
> 							forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
> 				}
> 			}
> As you can see, getSubString is called with first argument (start) equal to 1, even if length of CLOB is 0. Of course, it's not very good, but it worked for previous versions of Hibernate. But in 3.6.0 getSubString() handling in ClobProxy introduces additional checks that prevents the code above from working:
> if ( start > getLength() ) {
>     throw new SQLException( "Start position [" + start + "] cannot exceed overall CLOB length [" + getLength() + "]" );
> }
> Thus this code will now thrown an exception if content is empty (but not null!) CLOB. Here the part of stack trace:
> 31.10 16:46:03 .AbstractFlushingEventListener ERROR Could not synchronize database state with session
> org.hibernate.exception.GenericJDBCException: could not insert: [ru.arptek.classes.dummy.Article$Content]
>         at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
>         at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
>         at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
>         at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2436)
>         at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2856)
>         at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
>         at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
>         at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
>         at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
>         at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
>         at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
>         at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
>         at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:795)
>         at ru.arptek.arpsite.content.WebObjectHome.create(WebObjectHome.java:122)
> (...)
> Caused by: java.sql.SQLException: Start position [1] cannot exceed overall CLOB length [0]
>         at org.hibernate.engine.jdbc.ClobProxy.invoke(ClobProxy.java:146)
>         at $Proxy52.getSubString(Unknown Source)
>         at com.mysql.jdbc.PreparedStatement.setClob(PreparedStatement.java:3542)
>         at com.mysql.jdbc.jdbc2.optional.PreparedStatementWrapper.setClob(PreparedStatementWrapper.java:299)
>         at org.apache.commons.dbcp.DelegatingPreparedStatement.setClob(DelegatingPreparedStatement.java:187)
>         at org.apache.commons.dbcp.DelegatingPreparedStatement.setClob(DelegatingPreparedStatement.java:187)
>         at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$1.doBind(ClobTypeDescriptor.java:60)
>         at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:89)
>         at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:282)
>         at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:277)
>         at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:85)
>         at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2166)
>         at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2412)
>         ... 70 more
> I believe there should be additional check like:
> long start = (Long) args[0];
> if ( start < 1 ) {
>         throw new SQLException( "Start position 1-based; must be 1 or more." );
> }
> int length = (Integer) args[1];
> if ( length < 0 ) {
>         throw new SQLException( "Length must be great-than-or-equal to zero." );
> }
> // workaround for MySQL incompatibility
> if ( start == 1 && length == 0) {
>     return "";
> } else if ( start > getLength() ) {
>     throw new SQLException( "Start position [" + start + "] cannot exceed overall CLOB length [" + getLength() + "]" );
> }
> return getSubString( start-1, length );

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list