Java 通过 socket 获取 mysql 中的记录遇到的问题
在实际应用中,经常会遇到这种需求,客户端发送关键字到服务器端,服务器端根据关键字查找数据库中的内容并发送给客户端。本文主要阐述根据传输过来的关键字在查找数据库时查找不到(实际上是数据库中是有数据的)的问题,以及解决方法。
 
先看 Java 与 mysql 交互的代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 String driver = "com.mysql.jdbc.Driver"; // 驱动程序名  
 String url = "mysql的地址"; // URL指向要访问的数据库  
 String user = "用户名";  // MySQL配置时的用户名  
 String password = "你的密码"; // MySQL配置时的密码
Class.forName(driver);// 加载驱动程序  
Connection conn = DriverManager.getConnection(url, user, password);// 连接数据库  
if(!conn.isClosed())  
    System.out.println("成功连接到数据库!");
PreparedStatement prepstmt = null; //用预编译对象执行sql语句并返回结果  
String sql = "select admoment,url1,url2  from captiontest where filmname=? order by admoment";//要执行的SQL语句,按时间查找广告出现的数据记录  
prepstmt=conn.prepareStatement(sql);  
prepstmt.setString(1,name); // 由于filmnam是String类所以这里是setString,其他同理为setxxx(xxx为类型)  
ResultSet rs=prepstmt.executeQuery(); //结果集  
其中程序中的 name 为 String 类型,也就是客户端传过来的关键字,但是测试时的问题是即使数据库中存在相关的关键字信息,也不会输出相关信息。。
这个时候首先要做的就是将执行的 SQL 语句打印出来,因为很多时候得不到预期的结果都是因为是实际执行的 SQL 语句跟自己预期会执行的 SQL 语句不同。通过下面语句可以得出执行的 SQL 语句: System.out.println(prepstmt.toString());。
结果如下1
select admoment,url1,url2  from captiontest where filmname='爱情公寓4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\' order by admoment  
怪不得找不到,sql 语句都变成这个模样了,那中间的 \0 是从哪里来的?在网上查了后得出的原因如下:在 socket 传输自己流时,默认会有一段固定长度的 bufferstream 来接受传输的字节流,这段固定长度的默认值就是 \0 , 而那些 \0 就是 bufferstream 中没被传输过来的字节流覆盖的单元,解决方法也很简单,就是在服务器接受到客户端传输过来的字节流时,根据字节流有效长度来创建 String
原来我的 name 是这样产生的,is 是 socket 的输入流:1
2int n = is.read(b);  
String name=new String(b,"UTF-8");  
没有指定长度,改为下面的产生方式就好了1
2int n = is.read(b);  
String name=new String(b,0,n);//0和n是指定产生String用到的字节流的开头和结尾