Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > JSP->Oracle русский


Автор: mastanik 19.9.2006, 11:53
Здравствуйте,

такая проблема, никак не получается внести русский текст в Оракл 8.

в JSP пишу:
Код

<%@ page contentType="text/html;  Charset=utf-8" language="java"%>


в Оракле:
Код

NLS_CHARACTERSET = CL8ISO8859P5
NLS_NCHAR_CHARACTERSET = CL8ISO8859P5

Автор: jsa 19.9.2006, 11:56
а подробнее?

Автор: mastanik 19.9.2006, 12:12
при занесении данных в базе отображаются вопросы. 
менял необходимые поля с VARCHAR2 на NVARCHAR2 - Оракл ругается ошибкой 
ERROR at line 1:
ORA-12704: character set mismatch

Автор: y3u 19.9.2006, 13:33
как именно ты данные пишешь в БД? Какие параметры у коннектора ты используешь?

Автор: DEER 19.9.2006, 13:39
Цитата

Charset=utf-8


ИМХО. везде юзай cp121

Автор: mastanik 19.9.2006, 13:43
система по всей вероятности будет использоваться не только в русскоязычных странах, поэтому хочется уникодом пользоваться.

пишу так

Код

Class.forName("oracle.jdbc.OracleDriver");
        con = DriverManager.getConnection("jdbc:oracle:thin:@ююю:1521:ююю", "ююю", "ююю");
        con.setAutoCommit(false);
        Statement statement = con.createStatement();
        String sql;
        int row = 0;
        
        sql = "INSERT INTO t(name, role) VALUES(?,?)";    
        OraclePreparedStatement pstmt = (OraclePreparedStatement)con.prepareStatement(sql) ;
        pstmt.setString(1, name);
        pstmt.setString(2, role);
        pstmt.execute();

Автор: LSD 19.9.2006, 15:59
1. Раз в базе кодировка ISO-8859-5, то юникод тебе только в NVARCHAR2 светит.

2. Определи где ошибка: накидай маленькое приложение которое будет соединяться с БД и писать туда текс в поля VARCHAR2 на NVARCHAR2. Если запишется нормально надо разбираться с JSP, что там не так, иначе смотреть параметры соединения с базой.

Автор: 3x3 20.9.2006, 03:50
Цитата(mastanik @ 19.9.2006,  12:12)
при занесении данных в базе отображаются вопросы. 
менял необходимые поля с VARCHAR2 на NVARCHAR2 - Оракл ругается ошибкой 
ERROR at line 1:
ORA-12704: character set mismatch

На клиенте (т.е. где приложение, общающееся с базой) - какой NLS_LANG в окружении стоит? Какая версия базы? Если вы делаете те же самые запросы из sqlplus - что происходит?

Автор: mastanik 20.9.2006, 11:00
хмм, где посмотреть NLS_LANG клиента? (допустим это SQL Worksheet) БД - Oracle 8. 
делаю так, в поле с типом NVARCHAR2 вношу данные:

Код

insert into t(name) values('мастаник');


выдает:
Код

ERROR at line 1:
ORA-12704: character set mismatch


если поле типа VARCHAR2, то заносятся вопросы.

Автор: batigoal 20.9.2006, 11:44
Цитата(mastanik @  20.9.2006,  12:00 Найти цитируемый пост)
хмм, где посмотреть NLS_LANG клиента?

На винде - в реестре. HKEY_LOCAL_MACHINE --> Software --> Oracle.

Автор: mastanik 20.9.2006, 12:30
хм, NLS_LANG = N/A

Автор: 3x3 20.9.2006, 14:36
Цитата(mastanik @ 20.9.2006,  12:30)
хм, NLS_LANG = N/A

Ну и поставьте там что-нить типа "AMERICAN_AMERICA.CL8MSWIN1251", главное что бы он понял, что русскими буквами кормят, а не какими-нибудь там smile

Автор: jsa 20.9.2006, 15:09
Цитата(mastanik @ 19.9.2006,  13:43)
Код

Class.forName("oracle.jdbc.OracleDriver");
        con = DriverManager.getConnection("jdbc:oracle:thin:@ююю:1521:ююю", "ююю", "ююю");
        con.setAutoCommit(false);
        Statement statement = con.createStatement();
        String sql;
        int row = 0;
        
        sql = "INSERT INTO t(name, role) VALUES(?,?)";    
        OraclePreparedStatement pstmt = (OraclePreparedStatement)con.prepareStatement(sql) ;
        pstmt.setString(1, name);
        pstmt.setString(2, role);
        pstmt.execute();

откуда дровишки?  smile , т.е. откуда name, role, если постом получаешь, то они должны быть в ISO8859, по идее должны ложиться нормально
Цитата

при занесении данных в базе отображаются вопросы. 

чем смотришь, уверен что в базе вопросы, а может только на клиенте?

Автор: mastanik 21.9.2006, 10:03
прописал в реестре
 
AMERICAN_AMERICA.CL8MSWIN1251

те же вопросы.

Автор: 3x3 21.9.2006, 12:36
Боюсь, что всё может оказаться ещё хитрее. Во-первых ваш thin JDBC драйвер может не поддерживать русские кодировки. Т.е. будь у вас в базе 1251 и на клиенте 1251 - то он бы ещё может и гнал бы буквы напрямую без конверсии а так - кто его знает. Это касается именно thin-драйвера, который ходит в базу напрямую и не требует установки клиента. Скачайте с oracle.com свежую версию, там у них к JDBC пакет для интернационализации приложен.

Но для чистоты эксперимента попробуйте неск. вещей: 
 - выставить NLS_LANG как переменную окружения процесса, хотя лучше забивать в параметры самому соединению thin может вообще не ориентироваться на системные настройки: мало ли что там у юзера, загрузившего апплет, понастроено.
 - использовать не Ср1251, а UTF8 кодировку
 - убедитесь, что для сессии выставлена правильная кодировка: select * from nls_session_parameters (этот селект должен быть сделан из проблемной сессии)
 - отказаться от thin JDBC в пользу просто JDBC, который будет лазать в базу через её родной OCI. На сервере-то это даже и лучше. Но это путь для слабых духом. 


PS
Попробую поколбасить сегодня ночью thin JDBC от десятки, только не факт, что удастся воспроизвести проблему, у меня там в базе NLS_CHARACTERSET=UTF8 забит, да и вообще она десятка экспресс без поддержки российской локализации - когда они говорят "Европа", то, видимо подразумевают "Западная Европа".
Да, вот ещё страничка, на которой много полезного про Oracle JDBC-драйвера http://www.oracle.com/technology/tech/java/sqlj_jdbc/htdocs/jdbc_faq.htm#34_03

Автор: 3x3 22.9.2006, 03:26
Вобщем вот так у меня заработало в тестовом сервлете, и вставляет русские буквы (проверял в стороннем приложении в эту базу лазающем - буквы в таблице русские) и вынимает:

Код

Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();

java.util.Properties prop=new java.util.Properties();
prop.setProperty("NLS_LANG", "AMERICAN_AMERICA.UTF8");
prop.setProperty("user", "3х3");
prop.setProperty("password", "3+3+3");

Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost", prop);

// insert string "жзи", unicode entity used to ensure that it is really that string
PreparedStatement stmt = con.prepareStatement("insert into a values('\u0436\u0437\u0438')");
stmt.executeQuery();

stmt = con.prepareStatement("select a from a");
ResultSet rs = stmt.executeQuery();
int r=0;
while(rs.next()){
    String sss=null;
    sss=rs.getString(1);
    res+="<b>"+String.valueOf(r++)+" :</b>"+sss+"<br />";
}
con.rollback();

rs.close();
stmt.close();
con.close();


У вас должно и нормальное соединение зажить:
Код

Connection con = DriverManager.getConnection("jdbc:oracle:oci:@localhost", prop);


У меня jdbc:oracle:oci не живёт из-за небольшого насилия над базой по части юникода в varchar2 - ломается на длине русских строк. Похоже в штатном oci-клиенте до сих пор присутствует непонимание того, что буквы бывают длиннее одного байта. В общем было бы интересно узнать - заживут ли у вас оба драйвера.


Для теста использована таблица простейшей структуры:
Код

create table a (a varchar2(100));


По ходу отмечена проблемка в связи с тем, что rollback не откатывает транзакцию, но, думаю, это режим у JDBC-драйвера по умолчанию такой интересный, надо разбираться.


Автор: mastanik 27.9.2006, 16:30
А в БД какая кодировка настроена?

Автор: 3x3 27.9.2006, 17:07
Цитата(mastanik @ 27.9.2006,  16:30)
А в БД какая кодировка настроена?

UTF-8.
У меня сейчас европейский eXpress Edition стоит, русского NLS там нет вообще. Т.е. русских чарсетов нет, русской сортировки нет (не проверял, кстати), русских сообщений нет, русских дат нет. И UTF-8 я ему насильно прописал, только что-б буквы русские попробовать.

Без перекодировки (т.е. пришло в UTF8 и сохраняется в UTF8) - хоть русские буквы засовываются. Хотя varchar2 при этом считает длину не по количеству символов, а по количеству байтов, т.е. макс.допустимое количество букв в строке будет ниже указанного при создании таблицы ровно в два раза. Что бы в длине строк не зависеть от кодировки, с 9й версии можно задавать поля в символах:
    create table t 
      (  x varchar2( 20 CHAR ),
       ...
    )




Вам собственно нужно провести 2х3 экспериментов: используя oci и thin драйвера с кодировками как у Базы, UTF-8 и какую-нить 8-битную какую ваша Java понимает, 1251 например. При этом, на всякий случай, выставляйте соответствующий NLS_LANG и в окружении процесса.

Автор: mastanik 27.9.2006, 17:42
АААААААА!!!!!!!!
Кажись заработало! Спасибо огромное!!!!!!!

Автор: 3x3 27.9.2006, 19:25
Цитата(mastanik @ 27.9.2006,  17:42)
АААААААА!!!!!!!!
Кажись заработало! Спасибо огромное!!!!!!!

Ну так поделитесь чего и как заработало в вашей конкретной конфигурации. На будущее може ещё кому пригодится.

Автор: mastanik 28.9.2006, 12:31
Пример 3х3 заработал.

Автор: 3x3 28.9.2006, 15:11
Цитата(mastanik @ 28.9.2006,  12:31)
Пример 3х3 заработал.

ОК. По всей видимости из-за вот этого:
prop.setProperty("NLS_LANG", "AMERICAN_AMERICA.UTF8");

Тогда как резюме:

ИМХО можно сделать вывод, что thin-драйвер не полагается на настройки на клиенте - ведь он может и из апплетки работать на клиенте, который или настроен неправильно или вообще не знает про существование Oracle. Т.е. он полагается на дефолтные настройки базы, но ничего про ISO-8859-5, видимо, не знает - т.е. JVM не имеет установленных правил трансляции этой кодировки в юникод. 

Задав параметры соединения явно, вы указали базе во что она должна транслировать буквы перед отправкой их на клиента. Если это так, то вместо UTF8 должна бы и CL8MSWIN1251 работать, если она установлена на сервере БД и поддержана клиентской джавой.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)