前几天遇到这样的一种情况:
表单提交了一个日期,格式是 yyyy-mm-dd (前端插件输出的)。
我打算在后端做一个转换,将字符串时间转换成时间戳然后存入数据库:
Activity m = getModel(Activity.class);
m.set("start_time", Tools.datetimeToTimestamp(getPara("activity.start_time")));
m.save();
然后紧接着就遇到一个500,错误信息大概如下:
[ERROR]-[Thread: qtp16393153-18]-[com.jfinal.core.ActionHandler.handle()]: /act/new/save
java.lang.RuntimeException: Can not convert parameter: activity.start_timeCaused by: java.lang.NumberFormatException: For input string: "2015-06-01"
我以为弄错了,怀疑set并未起效然后翻到一篇文章:
http://www.oschina.net/question/245971_124636
发现方法完全一样。
最终才注意到,他的参数前后类型是相同的(str->str),而我的前后类型是不同的(str->long)。
我觉得完全没有必要这样啊,为什么数据都改变了,还要对旧数据进行类型转换呢?很不理解。
异常信息没贴完全,据推测 jdbc 在保存数据时,发现原本要求 starg_time 为datetime类型 却被传入的是 timestamp,从而造成的数据类型转换错误,这个转换 jfinal 并未干预,jfinal 只是直接把将参数和 sql 直接扔给了 jdbc,贴出更详细的异常,以及数据表结构才能弄清楚最终原因: desc tableName
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
数据表是这样的
mysql> desc activity;
+------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| uid | bigint(20) | NO | | NULL | |
| title | text | YES | | NULL | |
| brief | text | YES | | NULL | |
| content | text | YES | | NULL | |
| price | double | YES | | NULL | |
| post_time | bigint(20) | YES | | NULL | |
| start_time | bigint(20) | YES | | NULL | |
| over_time | bigint(20) | YES | | NULL | |
| state | int(11) | YES | | NULL | |
+------------+------------+------+-----+---------+----------------+
10 rows in set
因为是原型项目做的比较对付。
整篇的错误比较长 当时就没贴。如果你需要的话,我一会开起来项目弄一个完整版。
上面代码中的 Tools.datetimeToTimestamp(...) 返回值让它是 long 即可打完收工
start_time 是 bigint(20) 类型,那么jdbc 映射为的 java 类型是 Long型,所以出现这个问题非常诡异,按理说是正确的。我在 jfinal.com 中的 expireAt 字段就是这样用的,完全没事:
mysql> desc session;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| id | varchar(33) | NO | PRI | NULL | |
| accountId | int(11) | NO | | NULL | |
| expireAt | bigint(20) | NO | | NULL | |
+-----------+-------------+------+-----+---------+-------+
3 rows in set (0.14 sec)
调试一下 com.jfinal.plugin.activerecord.TableBuilder 看一下 start_time 是否被映射成了 Long 类型,你用的是哪个版本的 jfinal ?
我明天试一下。
当时提问题的时候,还是上一个版本,我换成2.0看看。
问题依旧存在,完整LOG如下:
2015-06-24 16:14:58
[ERROR]-[Thread: qtp16393153-22]-[com.jfinal.core.ActionHandler.handle()]: /act/new/save
java.lang.RuntimeException: Can not convert parameter: activity.start_time
at com.jfinal.core.ModelInjector.injectActiveRecordModel(ModelInjector.java:102)
at com.jfinal.core.ModelInjector.inject(ModelInjector.java:50)
at com.jfinal.core.ModelInjector.inject(ModelInjector.java:37)
at com.jfinal.core.Controller.getModel(Controller.java:647)
at tuan.action.activity.ActivityController.publishAdd(ActivityController.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.jfinal.aop.Invocation.invoke(Invocation.java:71)
at com.jfinal.validate.Validator.intercept(Validator.java:72)
at com.jfinal.aop.Invocation.invoke(Invocation.java:65)
at tuan.Interceptor.LoginInterceptor.intercept(LoginInterceptor.java:20)
at com.jfinal.aop.Invocation.invoke(Invocation.java:65)
at com.jfinal.ext.interceptor.POST.intercept(POST.java:30)
at com.jfinal.aop.Invocation.invoke(Invocation.java:65)
at tuan.Interceptor.JspInterceptor.intercept(JspInterceptor.java:26)
at com.jfinal.aop.Invocation.invoke(Invocation.java:65)
at com.jfinal.core.ActionHandler.handle(ActionHandler.java:74)
at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:72)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1307)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:453)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:560)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:365)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:937)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:998)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:856)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NumberFormatException: For input string: "2015-06-05"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:589)
at java.lang.Long.parseLong(Long.java:631)
at com.jfinal.core.TypeConverter.convert(TypeConverter.java:62)
at com.jfinal.core.ModelInjector.injectActiveRecordModel(ModelInjector.java:98)
... 42 more
代码如下:
@ActionKey("/act/new/save")
@Before({POST.class, LoginInterceptor.class, ActEditValidator.class})
public void publishAdd()
{
Activity m = getModel(Activity.class);
m.set("uid", getSessionAttr("user_id"));
m.set("start_time", Tools.datetimeToTimestamp(getPara("activity.start_time")));
m.set("over_time", Tools.datetimeToTimestamp(getPara("over_time")));
m.set("now_time", Tools.getNowTime());
m.set("state", ActivityState.SELLING.ordinal());
m.save(); // BUG: 这里居然无法修改数据
...
}
通过异常看到,你从前端页面传进去的参数是"2015-06-05",而 jfinal 在系统启动的时候通过反射 "activity.start_time"字段,断定该字断为 Long型,所以在 getModel 的时候会试图将 "2015-06-05" 转换成 Long 型数据,必须会抛出这个异常,简单解决办法是为个这段在前端取名为 "start_time" 而非 "activity.start_time",这样的话 getModel 就不会处理这个字段,然后再这样:m.set("start_time", Tools.datetimeToTimestamp(getPara("start_time")))
原来 getModel() 的时候就已经出错了吗?
这下我明白了来龙去脉,之前还以为是save的时候报错来着,怪不得会如此!
状态更改为 已关闭
登录 后才可以发表评论