2010-11-11 16 views
6

Próbuję użyć "New Methods for National Character Set Type Data in JDK 1.6", aby uzyskać standardowego JDBC rozwiązanie do obsługi cyrylicy znaków, ale gdy wykonanie osiągnie każdą linię typu nvarchar, na przykład :Korzystanie Types.NVARCHAR ze sterownika Oracle JDBC do pracy z cyrylicy znaków

preparedSelect.setObject(3, "суббота", Types.NVARCHAR); 

Następnie otrzymuję ten wyjątek:

java.sql.SQLException: Invalid column type 
    at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70) 
    at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:131) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:197) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:261) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:269) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:490) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:7922) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:7502) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:7975) 
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:222) 

próbowałem również użyć setNString(), ale pojawia się jeszcze bardziej dziwne wyjątek:

java.lang.AbstractMethodError: oracle.jdbc.driver.OraclePreparedStatementWrapper.setNString(ILjava/lang/String;)V 

Jeśli używam java -Doracle.jdbc.defaultNChar = true myApplication ze zwykłymi Typami.VARCHAR, rosyjskie słowa są przechowywane poprawnie. Ale używanie opcji -Doracle.jdbc.defaultNChar = true nie jest opcją, ponieważ pracuję nad starszą aplikacją, nie mam kontroli nad uruchomieniem środowiska produkcyjnego, po prostu piszę do niego komponent. Ponadto ten "Readme for NChar How-to" stwierdza, że ​​"ta konwersja ma znaczny wpływ na wydajność". Tak ustawia domyślnie wszystko do NChar, gdy tylko mniej niż 1% moich tabel potrzebuje tej konwersji, a nie jest to dobry wybór.

Używam cienkiego sterownika Oracle i mam plik ojdbc6.jar i orai18n.jar w mojej ścieżce klas.

Szukam standardowego rozwiązania JDBC. Nie mogę użyć żadnych metod lub stałych z "oracle" na nich. OraclePreparedStatement nie jest dla mnie opcją.

Próbowałem używać Types.NVARCHAR z serwerem MSSQL i działa dobrze.

+0

Próbowałaś użyciu setNString() i sprawdzić, czy to działa? –

+0

Edytowałem moje pytanie z aktualizacją o setNString() –

+0

Aby wykluczyć oczywiste: czy próbowałeś wywołać stare dobre 'setString()'? Z powodzeniem zapisałem w tym arabskie znaki. –

Odpowiedz

2

Znalazłem rozwiązanie!

Używałem ojdbc 11.2.0.1. Gdy przełączyłem się na 11.2.0.2, mogłem poprawnie pracować z setNString(). Ale nadal otrzymuję ten sam java.sql.SQLException: Invalid column type, jeśli używam setObject() z Type.NVARCHAR. Wstydź się Oracle ...

Zresztą rozwiązanie: przełącznik do ojdbc 11.2.0.2

0

Udało mi się sprawić, że działa to jakiś czas temu z następującymi inantacjami. Te metody są fragmentem większej klasy.

import com.mchange.v2.c3p0.C3P0ProxyStatement; 
import oracle.jdbc.OraclePreparedStatement; 

    static { 
     try { 
      SET_FORM_OF_USE_METHOD = OraclePreparedStatement.class.getDeclaredMethod("setFormOfUse", new Class[] { Integer.TYPE, Short.TYPE }); 
     } catch (NoSuchMethodException ex) { 
      LOG.fatal("Can't find the setFormOfUse method", ex); 
      throw new ExceptionInInitializerError(ex); 
     } 
    } 


    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException { 
     if (st instanceof OraclePreparedStatement) { 
      ((OraclePreparedStatement)st).setFormOfUse(index, OraclePreparedStatement.FORM_NCHAR); 
     } else if (st instanceof C3P0ProxyStatement) { 
      try { 
       C3P0ProxyStatement c3p0St = (C3P0ProxyStatement) st; 
       c3p0St.rawStatementOperation(SET_FORM_OF_USE_METHOD, C3P0ProxyStatement.RAW_STATEMENT, new Object[]{index, OraclePreparedStatement.FORM_NCHAR}); 
      } catch (IllegalAccessException ex) { 
       throw new UnexpectedException("Error calling setFormOfUse through C3P0", ex); 
      } catch (IllegalArgumentException ex) { 
       throw new UnexpectedException("Error calling setFormOfUse through C3P0", ex); 
      } catch (InvocationTargetException ex) { 
       throw new UnexpectedException("Error calling setFormOfUse through C3P0", ex); 
      } 
     } else { 
      throw new IllegalArgumentException("Unkown PreparedStatement implementation: " + st.getClass() + ". Maybe an unknown connection pool is hiding the OraclePreparedStatement?"); 
     } 

     st.setString(index, (String) value); 
    } 

Sposób nullSafeSet jest skonstruowany do pracy bezpośrednio w instancjach OraclePreparedStatement lub na C3P0ProxyStatement w przypadku gdy masz puli połączeń C3P0; inne opcje będą musiały być stosowane w przypadku różnych pul.

Ta metoda działała z plikiem ojdbc14.jar z Oracle 10.2.0.4.

+1

Problem z tym rozwiązaniem jest zależny od Oracle. Szukam czegoś standardowego JDBC, ponieważ nasz system działa zarówno na serwerze MSSQL, jak i na Oracle.Wygląda na to, że sterownik JDBC Microsoftu jest bardziej zgodny z Java niż sam "właściciel" Java. –

+0

Jeśli chodzi o domniemanie ojdbc14.jar, prawdopodobnie nie ma na to standardowej metody jdbc. Nie jestem pewien co do wersji sterownika, z której korzystasz; w każdym razie, jeśli to zadziała, możesz użyć go do wyroczni i powrócić do standardowego sposobu na wszystko inne. – Flavio

+2

Jak widać w "New Methods for National Character Set Data Type in JDK 1.6", mówią "użyj metody setFormOfUse ... ... jest odradzane, ponieważ ta metoda zostanie wycofana w przyszłym wydaniu", a także mówią: " Jeśli używana jest metoda setObject, docelowy typ danych musi być określony jako Typ.NCHAR, Types.NCLOB, Types.NVARCHAR lub Types.LONGNVARCHAR " –

Powiązane problemy