吴良超的学习笔记

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(); //结果集

其中程序中的 nameString 类型,也就是客户端传过来的关键字,但是测试时的问题是即使数据库中存在相关的关键字信息,也不会输出相关信息。

这个时候首先要做的就是将执行的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
2
int n = is.read(b);
String name=new String(b,"UTF-8");

没有指定长度,改为下面的产生方式就好了

1
2
int n = is.read(b);
String name=new String(b,0,n);//0和n是指定产生String用到的字节流的开头和结尾