开发者

Save and Load UTF-8 From Oracle 10g with iBatis

开发者 https://www.devze.com 2023-03-25 11:02 出处:网络
I\'m making a web app that needs to load and save UTF-8 (Korean, specifically) characters from a DB.I\'ve been given an account on the Oracle 10g server, but it saves VARCHAR2 type columns as ASCII7,

I'm making a web app that needs to load and save UTF-8 (Korean, specifically) characters from a DB. I've been given an account on the Oracle 10g server, but it saves VARCHAR2 type columns as ASCII7, with each UTF-8 character taking 2 VARCHAR2 slots.

I assumed that since iBatis is writing in the same way that it is reading, if I treat everything from input to output as UTF-8 I will have no problems, but any Korean characters I input come out garbled.

Is there a way to do this properly without messing up the (someone else's) DB?

Further information:

I've previously been able to load Korean strings using:

ResultSet rs = ps.executeQuery();
String koreanString = new String(rs.getBytes("colname"), "euc-kr");

And write Korean strings to db using:

PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, new String(koreanString.getBytes("euc-kr"), "ISO-8859-1"));

Attempts to change the JDBC connection url result in this message:

Description

Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
The Connection descriptor used by the client was:
[ip]:myTablespace?useUnicode=true&characterEncoding=UTF-8

error dump

javax.servlet.ServletException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
The Connection descriptor used by the client was:
[ip]:myTablespace?useUnicode=true&characterEncoding=UTF-8

at jeus.servlet.jsp2.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:859)
at jeus.servlet.jsp2.runtime.PageContextImpl.handlePageException(PageContextImpl.java:789)
at jeus_jspwork._jsp._500_managerAdmin_5fjsp._jspService(_500_managerAdmin_5fjsp.java:452)
at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:95)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:147)
at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:365)
at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:284)

root cause

java.sql.SQLException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
The Connection descriptor used by the client was:
[ip]:myTablespace?useUnico开发者_开发知识库de=true&characterEncoding=UTF-8

at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:261)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:441)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
at java.sql.DriverManager.getConnection(DriverManager.java:525)
at java.sql.DriverManager.getConnection(DriverManager.java:171)
at com.ibatis.common.jdbc.SimpleDataSource.popConnection(SimpleDataSource.java:580)
at com.ibatis.common.jdbc.SimpleDataSource.getConnection(SimpleDataSource.java:222)
at com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransaction.init(JdbcTransaction.java:48)
at com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransaction.getConnection(JdbcTransaction.java:89)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryForObject(MappedStatement.java:120)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:518)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:493)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:106)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:82)
at [].admRole.getCount(admRole.java:44)
at jeus_jspwork._jsp._500_managerAdmin_5fjsp._jspService(_500_managerAdmin_5fjsp.java:145)
at jeus.servlet.jsp2.runtime.HttpJspBase.service(HttpJspBase.java:95)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:147)
at jeus.servlet.servlets.JspServlet.execute(JspServlet.java:365)
at jeus.servlet.engine.HttpRequestProcessor.run(HttpRequestProcessor.java:284)


As I stated in the question, strings are stored and retrieved correctly if they are re-encoded as EUC-KR before being turned into ISO-8859-1 (to save, or vice versa to retrieve).

I modified the two following classes:

com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap

com.ibatis.sqlmap.engine.mapping.result.ResultMap

In both cases, I took the Object[] array (parameters and columnValues), casted to String, and applied the encoding transformations.


I am not using oracle for quite a while, but I have some confidence that this is reason of your "listener does not currently know of SID given" error: Can I force JDBC Driver use UTF-8 Charset to encode?

I am a Chinese developer so the character encoding problem is pretty much the same(we are mostly using GBK character set here). As far as I can remember, "but it saves VARCHAR2 type columns as ASCII7" means that your oracle instance is a non-unicode installation?

The force use of string.getBytes(charset) above JDBC layer is really really bad in terms of maintenance and data interpretability(the string data is displayed as a mess to DBA; DBA can not use SQL to perform any string comparison on this column, etc). So my advice is try to contact your DBA and get the database working with unicode first, since Oracle is very capable of handling unicode data.

0

精彩评论

暂无评论...
验证码 换一张
取 消