88import com .fasterxml .jackson .core .JsonGenerator ;
99import com .fasterxml .jackson .core .JsonParser ;
1010import oracle .jdbc .OracleType ;
11+ import oracle .jdbc .driver .DatabaseError ;
1112import oracle .sql .json .OracleJsonDatum ;
1213import oracle .sql .json .OracleJsonFactory ;
1314import oracle .sql .json .OracleJsonGenerator ;
1415import oracle .sql .json .OracleJsonParser ;
16+ import org .hibernate .internal .CoreLogging ;
17+ import org .hibernate .internal .CoreMessageLogger ;
1518import org .hibernate .metamodel .mapping .EmbeddableMappingType ;
1619import org .hibernate .metamodel .spi .RuntimeModelCreationContext ;
1720import org .hibernate .type .descriptor .ValueBinder ;
2225import org .hibernate .type .descriptor .jdbc .BasicBinder ;
2326import org .hibernate .type .descriptor .jdbc .BasicExtractor ;
2427import org .hibernate .type .format .FormatMapper ;
28+ import org .hibernate .type .format .OsonDocumentReader ;
2529import org .hibernate .type .format .OsonDocumentWriter ;
2630import org .hibernate .type .format .jackson .JacksonOsonFormatMapper ;
2731
32+ import java .io .ByteArrayInputStream ;
2833import java .io .ByteArrayOutputStream ;
2934import java .io .InputStream ;
3035import java .sql .CallableStatement ;
4348public class OracleOsonJacksonJdbcType extends OracleJsonJdbcType {
4449 public static final OracleOsonJacksonJdbcType INSTANCE = new OracleOsonJacksonJdbcType ( null );
4550
46- private static final Class osonFactoryKlass ;
51+ private static final CoreMessageLogger LOG = CoreLogging .messageLogger ( OracleOsonJacksonJdbcType .class );
52+
53+ private static final Object osonFactory ;
4754 static {
4855 try {
49- osonFactoryKlass = JacksonOsonFormatMapper .class .getClassLoader ().loadClass ( "oracle.jdbc.provider.oson.OsonFactory" );
56+ Class osonFactoryKlass = JacksonOsonFormatMapper .class .getClassLoader ().loadClass ( "oracle.jdbc.provider.oson.OsonFactory" );
57+ osonFactory = osonFactoryKlass .getDeclaredConstructor ().newInstance ();
5058 }
51- catch (ClassNotFoundException | LinkageError e ) {
59+ catch (Exception | LinkageError e ) {
5260 // should not happen as OracleOsonJacksonJdbcType is loaded
5361 // only when Oracle OSON JDBC extension is present
5462 // see OracleDialect class.
@@ -98,8 +106,7 @@ private <X> byte[] toOson(X value, JavaType<X> javaType, WrapperOptions options)
98106 }
99107
100108 ByteArrayOutputStream out = new ByteArrayOutputStream ();
101- JsonFactory osonFactory = (JsonFactory ) osonFactoryKlass .getDeclaredConstructor ().newInstance ();
102- try (JsonGenerator osonGen = osonFactory .createGenerator ( out )) {
109+ try (JsonGenerator osonGen = ((JsonFactory )osonFactory ).createGenerator ( out )) {
103110 mapper .writeToTarget ( value , javaType , osonGen , options );
104111 }
105112 return out .toByteArray ();
@@ -151,7 +158,7 @@ private X fromOson(InputStream osonBytes, WrapperOptions options) throws Excepti
151158 OracleJsonParser osonParser = new OracleJsonFactory ().createJsonBinaryParser ( osonBytes );
152159 Object [] objects = JsonHelper .deserialize (
153160 getEmbeddableMappingType (),
154- osonParser ,
161+ new OsonDocumentReader ( osonParser ) ,
155162 javaType .getJavaTypeClass () != Object [].class ,
156163 options
157164 );
@@ -164,12 +171,23 @@ private X fromOson(InputStream osonBytes, WrapperOptions options) throws Excepti
164171 type = (JavaType <X >) getEmbeddableMappingType ().getJavaType ();
165172 }
166173
167- JsonFactory osonFactory = (JsonFactory ) osonFactoryKlass .getDeclaredConstructor ().newInstance ();
168- try (JsonParser osonParser = osonFactory .createParser ( osonBytes )) {
174+ try (JsonParser osonParser = ((JsonFactory )osonFactory ).createParser ( osonBytes )) {
169175 return mapper .readFromSource ( type , osonParser , options );
170176 }
171177 }
172178
179+ private X doExtraction (byte [] bytes , WrapperOptions options ) throws SQLException {
180+ if ( bytes == null ) {
181+ return null ;
182+ }
183+
184+ try {
185+ return fromOson ( new ByteArrayInputStream (bytes ) ,options );
186+ }
187+ catch (Exception e ) {
188+ throw new SQLException ( e );
189+ }
190+ }
173191 private X doExtraction (OracleJsonDatum datum , WrapperOptions options ) throws SQLException {
174192 if ( datum == null ) {
175193 return null ;
@@ -185,22 +203,55 @@ private X doExtraction(OracleJsonDatum datum, WrapperOptions options) throws SQ
185203
186204 @ Override
187205 protected X doExtract (ResultSet rs , int paramIndex , WrapperOptions options ) throws SQLException {
188- OracleJsonDatum ojd = rs .getObject ( paramIndex , OracleJsonDatum .class );
189- return doExtraction (ojd ,options );
190-
206+ try {
207+ OracleJsonDatum ojd = rs .getObject ( paramIndex , OracleJsonDatum .class );
208+ return doExtraction (ojd ,options );
209+ } catch (SQLException exc ) {
210+ if ( exc .getErrorCode () == DatabaseError .EOJ_INVALID_COLUMN_TYPE ) {
211+ // this may happen if we are fetching data from an existing schema
212+ // that use CBLOB for JSON column
213+ LOG .invalidJSONColumnType ( OracleType .CLOB .getName (), OracleType .JSON .getName () );
214+ return doExtraction (rs .getBytes ( paramIndex ), options );
215+ } else {
216+ throw exc ;
217+ }
218+ }
191219 }
192220
193221 @ Override
194222 protected X doExtract (CallableStatement statement , int index , WrapperOptions options ) throws SQLException {
195- OracleJsonDatum ojd = statement .getObject ( index , OracleJsonDatum .class );
196- return doExtraction (ojd ,options );
223+ try {
224+ OracleJsonDatum ojd = statement .getObject ( index , OracleJsonDatum .class );
225+ return doExtraction (ojd ,options );
226+ } catch (SQLException exc ) {
227+ if ( exc .getErrorCode () == DatabaseError .EOJ_INVALID_COLUMN_TYPE ) {
228+ // this may happen if we are fetching data from an existing schema
229+ // that use CBLOB for JSON column
230+ LOG .invalidJSONColumnType ( OracleType .CLOB .getName (), OracleType .JSON .getName () );
231+ return doExtraction (statement .getBytes ( index ), options );
232+ } else {
233+ throw exc ;
234+ }
235+ }
197236 }
198237
199238 @ Override
200239 protected X doExtract (CallableStatement statement , String name , WrapperOptions options )
201240 throws SQLException {
202- OracleJsonDatum ojd = statement .getObject ( name , OracleJsonDatum .class );
203- return doExtraction (ojd ,options );
241+ try {
242+ OracleJsonDatum ojd = statement .getObject ( name , OracleJsonDatum .class );
243+ return doExtraction (ojd ,options );
244+ } catch (SQLException exc ) {
245+ if ( exc .getErrorCode () == DatabaseError .EOJ_INVALID_COLUMN_TYPE ) {
246+ // this may happen if we are fetching data from an existing schema
247+ // that use CBLOB for JSON column
248+ LOG .invalidJSONColumnType ( OracleType .CLOB .getName (), OracleType .JSON .getName () );
249+ return doExtraction (statement .getBytes ( name ), options );
250+ } else {
251+ throw exc ;
252+ }
253+ }
254+
204255 }
205256
206257 };
0 commit comments