Unknown column 'id' in 'where clause'

使用Users.dao.findById(..)或者Db.findById(..)会报错,是因为主键名必须是id才能用吗?


Users.dao.findById(name, "upass").set("upass", passwd_new).update();

报错:Unknown column 'id' in 'where clause'

---------------------------------------

Record user = Db.findById("users", "uname", name, "upass").set("upass", passwd_new);

Db.update("users", user);/Db.update(tableName, primaryKey, record);

报错: You can't update model without Primary Key.

-------------------



通过主键直接进行修改,怎么总是报错,这个是不是bug?

评论区

JFinal

2016-09-02 10:21

主键名可以是任意合法名称,不一定是 "id"
如果是 Model ,需要在 arp.addMapping(tableName, idName, modelClass) 时指定这个 idName,如果使用 jfinal 2.2 生成器,会自动生成映射,不需要处理
如果是 Db.find 的形式查询,需要在查询的时候临时提供 idName,例如:Db.findById(tableName, idName, idValue)

java180

2016-09-02 10:25

Db.的update方法倒是可以输入主键名,但是其中有一个参数是Number idValue,是说主键必须是整型的才能使用吗?

还有个反馈,这个反馈区域发布的信息,不能修改哦

java180

2016-09-02 10:35

@JFinal Db临时提供的idName能获取;
但是到了最后要update的时候,还是提示说You can't update model without Primary Key.

JFinal

2016-09-02 10:38

@java180 arp.addMapping(...) 的时候指定了 idName 没有? 方法原型是:addMapping(String tableName, String primaryKey, Class> modelClass),注意第二个参数就是主键名称,如果是复合主键就用逗号分隔: "id1, id2"

java180

2016-09-02 10:39

@JFinal 就是按照你的方法去把主键名添加进去了,还是不行啊

JFinal

2016-09-02 10:40

@java180 一定可以的,可能是别的原因造成的,例如eclipse自动编译是否打开,修改的代码是否生效之类的错误

java180

2016-09-02 10:42

@JFinal 好了!估计是这个tomcat的问题,我把整个项目删了重新发布了一下,就好了!谢谢老大!

JFinal

2016-09-02 10:43

@java180 多多关注社区动态,社区会一直有好用的功能添加

JFinal

2016-09-02 10:43

@java180 感谢支持社区发展

java180

2016-09-02 11:00

@JFinal 老大,我高兴的太早了,原来发布的是我改回去用sql语句update的,改了那个addmapping,不再报错unknown column id;

但是在update的时候,仍然报错 You can't update model without Primary Key

JFinal

2016-09-02 11:07

@java180 调试一下,看 update() 的时候,主键所对应的值是不是为 null? 没有值的时候才会报这个异常,你是不是在取值的时候没有取主键值?

java180

2016-09-02 11:24

@JFinal

都试了一遍,得出几个:
1.addmapping里面添加主键,是针对dao使用的,如果使用Db依然需要通过主键名,否则还是会报错Unknow column id;

2.dao的update方法,没有参数,只有一个方法,提交会报错without primary key

3.Db的update有8种方法,四个DataSource我没有用到,两个sql的没有问题,剩下两种带表名的都试了,依然报错without primary key
Db.update("users", user);
Db.update("users", "uname", user);

JFinal

2016-09-02 11:54

@java180 其实我的第一个回复已经说过了,model 主键要使用 arp.addMapping(...) 的第二个参数指定 idName,Db 的相关方法需要临时指定 idName。
此外, dao 的 update() 绝对不可以去调用它,这个在手册中强调过,dao 是全局共享的,只能用于查询

JFinal

2016-09-02 12:10

@java180 再补充一句:无论是 model 还是 Db,当主键名称为 "id" 时就不需要指定了,在没有指定 idName 时,jfinal 会使用默认的名称 "id",这个默认名称还可以在 Dialect 中可以自己指定

JFinal

2016-09-02 12:12

对于 model 来说,只要在 arp.addMapping(...) 一次性搞定,在使用过程中不再需要处理,而 Db.find/query 由于没有建立 table 的 meta 映射,所以,需要在使用过程中临时指定

java180

2016-09-03 21:02

@JFinal 老大,手册里5.3下面的例子你用了例子:
User.dao.findByIdLoadColumns (25).set("name", "James").update();

下面是注意:
User 中定义的 public static final User dao 对象是全局共享的, 只能用于数据库查询,
不能用于数据承载对象。 数据承载需要使用 new User().set(…)来实现。

这两个怎么理解啊?不能用于数据承载对象是什么意思呢?

JFinal

2016-09-03 21:07

@java180 手册 5.3 中的例子,User.dao 后面紧跟的是一个查询方法,而不是 set、update、save 方法。原因是 dao 对象是 static 修饰过的,那么地方面使用 User.dao.save()、update()、set() 之类的方法时,都是共享的这一个 dao 对象,假如线程 A 往里面 set 一个值进去,线程 B 再 save() 或者 update()这样数据就乱套了,这个是最基本的 java 线程安全问题

JFinal

2016-09-03 21:09

当一个对象用了 static 修饰,变成了全局共享变量,就必须要注意线程安全问题,而 dao 中的查询方法获取到的数据全部是 new 出来的,所以是线程安全的。

由于一些 jfinal 用户还没有掌握基本的线程安全知识,所以 jfinal 官方在未来出的任何 demo 也好,开源项目也好,都会完全删除 Model 中的 dao 对象,让你没法再犯这个错误

JFinal

2016-09-03 21:10

我现在对大家有一个建议:果断删掉 model 中定义的那个 dao 对象,不要再这样用了

Romeo

2016-09-05 14:35

@JFinal 那现在dao都要手动 new吗? 用dao对象是不是有线程安全的问题。。

JFinal

2016-09-05 14:36

@Romeo 不用手动 new,放在业务层就好,没有人会这么用:UserService.me().dao.save(),但有人会这么用: User.dao.save()

热门反馈

扫码入社