44 */
55package org .hibernate .dialect ;
66
7- import com .fasterxml .jackson .core .JsonParser ;
87import oracle .jdbc .OracleType ;
98import oracle .jdbc .driver .DatabaseError ;
109import oracle .sql .json .OracleJsonDatum ;
2827import org .hibernate .type .format .OsonDocumentWriter ;
2928
3029import java .io .ByteArrayOutputStream ;
30+ import java .io .Closeable ;
3131import java .io .InputStream ;
3232import java .nio .charset .StandardCharsets ;
3333import java .sql .CallableStatement ;
3434import java .sql .PreparedStatement ;
3535import java .sql .ResultSet ;
3636import java .sql .SQLException ;
3737
38- import static org .hibernate .dialect .OracleOsonJacksonJdbcType .OSON_JACKSON_FACTORY ;
39- import static org .hibernate .dialect .OracleOsonJacksonJdbcType .OSON_JSON_FACTORY ;
38+ import static org .hibernate .dialect .OracleOsonJdbcType .OSON_JSON_FACTORY ;
4039
4140/**
4241 *
4746 * @author Emmanuel Jannetti
4847 * @author Bidyadhar Mohanty
4948 */
50- public class OracleOsonJacksonArrayJdbcType extends OracleJsonArrayJdbcType {
49+ public class OracleOsonArrayJdbcType extends OracleJsonArrayJdbcType {
5150
52- private static final CoreMessageLogger LOG = CoreLogging .messageLogger ( OracleOsonJacksonArrayJdbcType .class );
51+ private static final CoreMessageLogger LOG = CoreLogging .messageLogger ( OracleOsonArrayJdbcType .class );
5352
54- public OracleOsonJacksonArrayJdbcType (JdbcType elementJdbcType ) {
53+ public OracleOsonArrayJdbcType (JdbcType elementJdbcType ) {
5554 super (elementJdbcType );
5655 }
5756
58-
5957 @ Override
6058 public String toString () {
61- return "OracleOsonJacksonArrayJdbcType " ;
59+ return "OracleOsonArrayJdbcType " ;
6260 }
6361
64-
6562 @ Override
6663 public <X > ValueBinder <X > getBinder (JavaType <X > javaType ) {
6764
@@ -73,7 +70,9 @@ private <T> byte[] toOsonStream(T value, JavaType<T> javaType, WrapperOptions op
7370 try (OracleJsonGenerator generator = OSON_JSON_FACTORY .createJsonBinaryGenerator ( out )) {
7471 final JavaType <?> elementJavaType = ((BasicPluralJavaType <?>) javaType ).getElementJavaType ();
7572 if ( elementJavaType instanceof UnknownBasicJavaType <?> ) {
76- options .getJsonFormatMapper ().writeToTarget ( value , javaType , generator , options );
73+ try (Closeable osonGen = OracleOsonJacksonHelper .createWriteTarget ( out )) {
74+ options .getJsonFormatMapper ().writeToTarget ( value , javaType , osonGen , options );
75+ }
7776 }
7877 else {
7978 final OsonDocumentWriter writer = new OsonDocumentWriter ( generator );
@@ -92,15 +91,31 @@ private <T> byte[] toOsonStream(T value, JavaType<T> javaType, WrapperOptions op
9291 );
9392 }
9493 }
95- return out .toByteArray ();
9694 }
95+ return out .toByteArray ();
96+ }
9797
98+ private boolean useUtf8 (WrapperOptions options ) {
99+ final JavaType <?> elementJavaType = ((BasicPluralJavaType <?>) getJavaType ()).getElementJavaType ();
100+ return elementJavaType instanceof UnknownBasicJavaType <?>
101+ && !options .getJsonFormatMapper ().supportsTargetType ( OracleOsonJacksonHelper .WRITER_CLASS );
98102 }
103+
99104 @ Override
100105 protected void doBind (PreparedStatement st , X value , int index , WrapperOptions options )
101106 throws SQLException {
102107 try {
103- st .setObject ( index , toOsonStream ( value , getJavaType (), options ), OracleType .JSON );
108+ if ( useUtf8 ( options ) ) {
109+ final String json = OracleOsonArrayJdbcType .this .toString (
110+ value ,
111+ getJavaType (),
112+ options
113+ );
114+ st .setBytes ( index , json .getBytes ( StandardCharsets .UTF_8 ) );
115+ }
116+ else {
117+ st .setObject ( index , toOsonStream ( value , getJavaType (), options ), OracleType .JSON );
118+ }
104119 }
105120 catch (Exception e ) {
106121 throw new SQLException ( e );
@@ -111,7 +126,17 @@ protected void doBind(PreparedStatement st, X value, int index, WrapperOptions o
111126 protected void doBind (CallableStatement st , X value , String name , WrapperOptions options )
112127 throws SQLException {
113128 try {
114- st .setObject ( name , toOsonStream ( value , getJavaType (), options ) , OracleType .JSON );
129+ if ( useUtf8 ( options ) ) {
130+ final String json = OracleOsonArrayJdbcType .this .toString (
131+ value ,
132+ getJavaType (),
133+ options
134+ );
135+ st .setBytes ( name , json .getBytes ( StandardCharsets .UTF_8 ) );
136+ }
137+ else {
138+ st .setObject ( name , toOsonStream ( value , getJavaType (), options ), OracleType .JSON );
139+ }
115140 }
116141 catch (Exception e ) {
117142 throw new SQLException ( e );
@@ -127,7 +152,7 @@ public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
127152
128153 private X fromOson (InputStream osonBytes , WrapperOptions options ) throws Exception {
129154 if ( ((BasicPluralJavaType <?>) getJavaType ()).getElementJavaType () instanceof UnknownBasicJavaType <?> ) {
130- try (JsonParser oParser = OSON_JACKSON_FACTORY . createParser ( osonBytes )) {
155+ try (Closeable oParser = OracleOsonJacksonHelper . createReadSource ( osonBytes )) {
131156 return options .getJsonFormatMapper ().readFromSource ( getJavaType (), oParser , options );
132157 }
133158 }
@@ -155,21 +180,40 @@ private X doExtraction(OracleJsonDatum datum, WrapperOptions options) throws SQ
155180 }
156181 }
157182
183+ private boolean useUtf8 (WrapperOptions options ) {
184+ final JavaType <?> elementJavaType = ((BasicPluralJavaType <?>) getJavaType ()).getElementJavaType ();
185+ return elementJavaType instanceof UnknownBasicJavaType <?>
186+ && !options .getJsonFormatMapper ().supportsTargetType ( OracleOsonJacksonHelper .READER_CLASS );
187+ }
188+
189+ private X fromString (byte [] json , WrapperOptions options ) throws SQLException {
190+ if ( json == null ) {
191+ return null ;
192+ }
193+ return OracleOsonArrayJdbcType .this .fromString (
194+ new String ( json , StandardCharsets .UTF_8 ),
195+ getJavaType (),
196+ options
197+ );
198+ }
199+
158200 @ Override
159201 protected X doExtract (ResultSet rs , int paramIndex , WrapperOptions options ) throws SQLException {
160202 try {
161- OracleJsonDatum ojd = rs .getObject ( paramIndex , OracleJsonDatum .class );
162- return doExtraction ( ojd , options );
203+ if ( useUtf8 ( options ) ) {
204+ return fromString ( rs .getBytes ( paramIndex ), options );
205+ }
206+ else {
207+ OracleJsonDatum ojd = rs .getObject ( paramIndex , OracleJsonDatum .class );
208+ return doExtraction ( ojd , options );
209+ }
163210 } catch (SQLException exc ) {
164211 if ( exc .getErrorCode () == DatabaseError .JDBC_ERROR_BASE + DatabaseError .EOJ_INVALID_COLUMN_TYPE ) {
165212 // This may happen if we are fetching data from an existing schema
166213 // that uses BLOB for JSON column In that case we assume bytes are
167214 // UTF-8 bytes (i.e not OSON) and we fall back to previous String-based implementation
168215 LOG .invalidJSONColumnType ( OracleType .CLOB .getName (), OracleType .JSON .getName () );
169- return OracleOsonJacksonArrayJdbcType .this .fromString (
170- new String ( rs .getBytes ( paramIndex ), StandardCharsets .UTF_8 ),
171- getJavaType (),
172- options );
216+ return fromString ( rs .getBytes ( paramIndex ), options );
173217 } else {
174218 throw exc ;
175219 }
@@ -179,18 +223,20 @@ protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) thro
179223 @ Override
180224 protected X doExtract (CallableStatement statement , int index , WrapperOptions options ) throws SQLException {
181225 try {
182- OracleJsonDatum ojd = statement .getObject ( index , OracleJsonDatum .class );
183- return doExtraction ( ojd , options );
226+ if ( useUtf8 ( options ) ) {
227+ return fromString ( statement .getBytes ( index ), options );
228+ }
229+ else {
230+ OracleJsonDatum ojd = statement .getObject ( index , OracleJsonDatum .class );
231+ return doExtraction ( ojd , options );
232+ }
184233 } catch (SQLException exc ) {
185234 if ( exc .getErrorCode () == DatabaseError .JDBC_ERROR_BASE + DatabaseError .EOJ_INVALID_COLUMN_TYPE ) {
186235 // This may happen if we are fetching data from an existing schema
187236 // that uses BLOB for JSON column In that case we assume bytes are
188237 // UTF-8 bytes (i.e not OSON) and we fall back to previous String-based implementation
189238 LOG .invalidJSONColumnType ( OracleType .CLOB .getName (), OracleType .JSON .getName () );
190- return OracleOsonJacksonArrayJdbcType .this .fromString (
191- new String ( statement .getBytes ( index ), StandardCharsets .UTF_8 ),
192- getJavaType (),
193- options );
239+ return fromString ( statement .getBytes ( index ), options );
194240 } else {
195241 throw exc ;
196242 }
@@ -201,18 +247,20 @@ protected X doExtract(CallableStatement statement, int index, WrapperOptions opt
201247 protected X doExtract (CallableStatement statement , String name , WrapperOptions options )
202248 throws SQLException {
203249 try {
204- OracleJsonDatum ojd = statement .getObject ( name , OracleJsonDatum .class );
205- return doExtraction ( ojd , options );
250+ if ( useUtf8 ( options ) ) {
251+ return fromString ( statement .getBytes ( name ), options );
252+ }
253+ else {
254+ OracleJsonDatum ojd = statement .getObject ( name , OracleJsonDatum .class );
255+ return doExtraction ( ojd , options );
256+ }
206257 } catch (SQLException exc ) {
207258 if ( exc .getErrorCode () == DatabaseError .JDBC_ERROR_BASE + DatabaseError .EOJ_INVALID_COLUMN_TYPE ) {
208259 // This may happen if we are fetching data from an existing schema
209260 // that uses BLOB for JSON column In that case we assume bytes are
210261 // UTF-8 bytes (i.e not OSON) and we fall back to previous String-based implementation
211262 LOG .invalidJSONColumnType ( OracleType .CLOB .getName (), OracleType .JSON .getName () );
212- return OracleOsonJacksonArrayJdbcType .this .fromString (
213- new String ( statement .getBytes ( name ), StandardCharsets .UTF_8 ),
214- getJavaType (),
215- options );
263+ return fromString ( statement .getBytes ( name ), options );
216264 } else {
217265 throw exc ;
218266 }
0 commit comments