论坛首页 Java企业应用论坛

hibernate+mysql的中文写入问题

浏览 6998 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-03-09  
今天折腾了一天了.
英文版win xp ,时区已设为中国,系统字符集已确认是gbk
jdb1.4.2
mysql 4.0.18 + mysql-connector-java-3.0.11-stable-bin.jar
hibernate 2.1

mysql的default_charater_set=gbk
jdbc的url=jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=gbk

DB中有正常的中文数据.
从数据库中读取已有的中文数据正常: po.getName()可打印出正常中文.

我在源码中,如果用po.setName(new String("中文".getBytes("GBK"),"ISO_8859_1")),是可以写入DB的. 只是变成了"????"号.
如果直接po.setName("中文"),写入时则报StringIndexOutOfBoundsException.
如果po.setName(other正常po.getName()),写入报StringIndexOutOfBoundsException.

各位可否指点一下?

附log:
中文
java.lang.StringIndexOutOfBoundsException: String index out of range: 4
        at java.lang.String.charAt(String.java:444)
        at com.mysql.jdbc.StringUtils.escapeSJISByteStream(StringUtils.java:340)

        at com.mysql.jdbc.StringUtils.getBytes(StringUtils.java:117)
        at com.mysql.jdbc.PreparedStatement.setString(PreparedStatement.java:1142)
        at org.apache.commons.dbcp.DelegatingPreparedStatement.setString(DelegatingPreparedStatement.java:243)
        at net.sf.hibernate.type.StringType.set(StringType.java:26)
   发表时间:2004-03-09  
change another driver,maybe
you can try mm.mysql 2.0.14
0 请登录后投票
   发表时间:2004-03-09  
thatway 写道
我在源码中,如果用po.setName(new String("中文".getBytes("GBK"),"ISO_8859_1")),是可以写入DB的. 只是变成了"????"号.


最好不要在Java Class里写中文(以前中过招,有空再详细讲:-D)。如果是WEB应用,可以写一个JSP,然后在FORM里加几个<input type=text ...>,服务端System.out.println(request.getParameter...)来测中文内容。

而且要注意你的应用服务器,不同的应用服务器会对Request.GetCharactorEncoding产生不同的影响。一般比较简便的方法是,写一个专门来设Encoding的Filter(可以在网上,或这个论坛上找找)。
0 请登录后投票
   发表时间:2004-03-09  
首先谢谢两位回答.

这是用旧驱动的出错信息:
22:18:00,840 ERROR AssertionFailure:27 - an assertion failure occured (this mayindicate a bug in Hibernate, but is more likely due to unsafe use of the session)
java.lang.reflect.InvocationTargetException

下面是用页面后的信息:
取页面参数前request.setCharactorEncoding("GBK");
System.out.println出来的中文是正确的.
写入数据库时,Exception照旧.

真想撞墙啊.
0 请登录后投票
   发表时间:2004-03-09  
试到现在,终于找到了一个可行的办法,虽然觉得不是很理想.

问题归结到以下三件事物的搭配使用:
1)mysql jdbc driver (2.0.14 or 3.0.11)
2)dialect (MySQLDialect or GenericDialect)
3)generator (increment,  identity or native)

一个可行的搭配是: 2.0.14 + MySQLDialect + increment.

这里我有一个疑问,劳烦各位.
increment(递增)
用于为long, short或者int类型生成唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。 在集群下不要使用。

"进程"是什么意思?和多线程读写DB有没有关系? 还是说只要在同一个JVM中访问DB就没问题?
0 请登录后投票
   发表时间:2004-03-10  
因为Hibernate说到底,还是要生成SQL帮你做事情。数据库表里的自增类型是能够保证,不管多少外部时程,向表里添加数据,自增字段都会保证唯一。

但如果你要在Java程序一层用自增来保证唯一就有点困难了。你可以在Java程序里用锁,也就是同步来保证所有的程序都是通过一个入口来进行插入数据的操作。所以也很好理解,不同的JVM里如果也这样插入数据,就很难用自增来保证唯一了。一般用用Increment不会有大问题,如果对唯一有强烈(:-))要求的,可以用UUID,一个肯定不会重复的字符串。
0 请登录后投票
   发表时间:2004-03-10  
thx chen.  问题最终解决了.:) 如下:

winter_lau 写道
最开始使用mysql提供的3.0.6版本的驱动一点都跑不了,一大堆乱七八糟的错误.
而后换成旧的org.gjt.mm.mysql.Driver就可以跑,但是要求对写入的字串转码->8859_1,但是读取的时候无需转码,晕!
最后到mysql网站下载最新的3.0.11驱动,这回好像没问题了,没有任何转码网页显示正常,但是一旦涉及到插入、修改的操作就报StringIndexOutOfBoundsException异常,只好打开mysql的驱动源码看了看加上一个字符串溢出的判断,整个世界清净了:)
(类com.mysql.jdbc.StringUtils的第280行修改为如下,黑体的为新增的代码)
if (strIndex<origString.length() && origString.charAt(strIndex) == '\\')
0 请登录后投票
   发表时间:2004-03-11  
winter_lau 写道
但是要求对写入的字串转码->8859_1,


这个转码绝对不是一种解决方法,就算是,也是一种中等偏下的解决方法。
0 请登录后投票
   发表时间:2004-03-11  
liang_chen 写道

这个转码绝对不是一种解决方法,就算是,也是一种中等偏下的解决方法。


能否推荐一下这方面的资料?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics