Skip to content
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

LONGVARCHAR is mapped to ClobTypeHandler #1484

Closed
yukihane opened this Issue Feb 21, 2019 · 2 comments

Comments

Projects
None yet
3 participants
@yukihane
Copy link

yukihane commented Feb 21, 2019

Default type handler of LONGVARCHAR is ClobTypeHandler.
ClobTypeHandler calls getClob, but LONGVARCHAR does not support it.
It is supported only on CLOB and NCLOB(*1).

*1: JSR-000221 JDBC API Specification 4.3 pp.200, TABLE B-6 Use of ResultSet getter Methods to Retrieve JDBC Data Types

It seems ver.3.4 improvement works, related to #248, may be wrong.

MyBatis version

3.5.0

Database vendor and version

SAP Adaptive Server Enterprise Express Edition 16.0 SP03

JDBC driver:
jConnect (TM) for JDBC(TM)/16.0 SP03 PL02 (Build 27403)/P/EBF27518/JDK 1.6.0/jdbcmain/OPT/Mon Aug 28 18:41:14 PDT 2017

Test case or example project

https://github.com/yukihane/mybatis-longvarchar

Steps to reproduce

Create LONGVARCHAR column:

create table longvarchar_table (
  longvarchar_column char(1024)
)

(ASE's char(1024) is JDBC LONGVARCHAR.)

Execute query, defined as:

@Mapper
public interface LongvarcharTableMapper {
    @Select("select longvarchar_column from longvarchar_table")
    List<String> select();
}

Expected result

query completion normally

Actual result

Exception occurs:

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'longvarchar_column' from result set.  Cause: java.sql.SQLException: JZ0TE: Attempted conversion between an illegal pair of types. Valid database datatypes are: '(text, Clob) (unitext, Clob) (unitext, NClob) (unitext, Clob) (image, Blob)'
### The error may exist in com/github/yukihane/mybatis/mapper/LongvarcharTableMapper.java (best guess)
### The error may involve com.github.yukihane.mybatis.mapper.LongvarcharTableMapper.select
### The error occurred while handling results
### SQL: select longvarchar_column from longvarchar_table
### Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'longvarchar_column' from result set.  Cause: java.sql.SQLException: JZ0TE: Attempted conversion between an illegal pair of types. Valid database datatypes are: '(text, Clob) (unitext, Clob) (unitext, NClob) (unitext, Clob) (image, Blob)'
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
    at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:144)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:77)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58)
    at com.sun.proxy.$Proxy10.select(Unknown Source)
    at com.github.yukihane.mybatis.mapper.LongvarcharTableMapperTest.test(LongvarcharTableMapperTest.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'longvarchar_column' from result set.  Cause: java.sql.SQLException: JZ0TE: Attempted conversion between an illegal pair of types. Valid database datatypes are: '(text, Clob) (unitext, Clob) (unitext, NClob) (unitext, Clob) (image, Blob)'
    at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:83)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createPrimitiveResultObject(DefaultResultSetHandler.java:713)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:612)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:591)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:397)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:354)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:328)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:301)
    at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:194)
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
    at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
    at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)
    at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:83)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
    ... 35 more
Caused by: java.sql.SQLException: JZ0TE: Attempted conversion between an illegal pair of types. Valid database datatypes are: '(text, Clob) (unitext, Clob) (unitext, NClob) (unitext, Clob) (image, Blob)'
    at com.sybase.jdbc4.jdbc.ErrorMessage.raiseError(ErrorMessage.java:767)
    at com.sybase.jdbc4.tds.TdsJdbcInputStream.getClob(TdsJdbcInputStream.java:2505)
    at com.sybase.jdbc4.jdbc.SybResultSet.getClob(SybResultSet.java:2485)
    at com.sybase.jdbc4.jdbc.SybResultSet.getClob(SybResultSet.java:2592)
    at org.apache.ibatis.type.ClobTypeHandler.getNullableResult(ClobTypeHandler.java:40)
    at org.apache.ibatis.type.ClobTypeHandler.getNullableResult(ClobTypeHandler.java:28)
    at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:81)
    ... 51 more

Workaround

Override default handler with StringTypeHandler.

LONGVARCHAR should support getString.(*1, pp.199)

@harawata

This comment has been minimized.

Copy link
Member

harawata commented Feb 21, 2019

@yukihane ,
Thank you for the detailed report!
StringTypeHandler seems to be a better fit for LONGVARCHAR indeed.
We should consider switching the default type handler in TypeHandlerRegistry.

@cbegin @jeffgbutler ,
I checked the commit log and ML posts, but couldn't find the reason why ClobTypeHandler was chosen for LONGVARCHAR in the first place.
Any concern about the switch?

@harawata

This comment has been minimized.

Copy link
Member

harawata commented Mar 6, 2019

Hi @yukihane ,
The change has been committed (thank you @kazuki43zoo for taking a look at the PR!).
I'd appreciate if you could verify the fix with the latest 3.5.1-SNAPSHOT, just to be sure.
Thanks again!

@kazuki43zoo kazuki43zoo added this to the 3.5.1 milestone Mar 6, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.