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