今天在调用Controller接口给Mysql数据库插入数据时,出现报错如下:
java.sql.SQLException: Field 'id' doesn't have a default value
通过查看报错信息可知:是因为字段 oid 没有默认值. 很奇怪的错误信息,因为我在Controller层明明给oid赋值了:
通过查看网上的资料,发现解决方法几乎都是说:
让你把数据库主键设置为自增就可以了!
虽然oid确实是主键没有错,但是为什么主键就一定要自增才能成功呢?难道所有实体类的主键都要设置为自增么?要是我就想自己赋值呢?
很可惜的是这些文章中并没有解释到这个更深层的原因!这就涉及到"授之以渔不如授之以鱼"的道理了!
比起告诉我怎么做,我更想知道的是为什么要这样做!
通过分析主键自增问题,我们可以先把注意力集中到数据库表中去:
通过表属性可知,我的主键确实没有设置自增,而如果我设置了自增的话,也确实是可以正常启动项目了! 但是存在一个大问题: 那就是如果我手动给oid赋值的话,就会无效,数据库会依旧按照自增的规则来给oid赋值: 也就是说手动赋值和自增只能取其一,并且当设置了自增后,手动赋值会无效! 这不是我想要的结果,那么能不能让手动给主键oid赋值成功呢? 既然数据库不能解决这个问题,我们只能去查看model实体类了,通过查看配置可以发现: 我在实体类中用到了 @GeneratedValue 这个注解,再看strategy的值是GenerationType.IDENTITY,才发现问题所在!!!因为: GenerationType.IDENTITY 主键生成策略的特点是:
主键由数据库生成, 必须采用数据库自增长方式(否则dao层插入数据会报错), 但Oracle不支持这种方式.因此想要实现我的想法,就必须修改 strategy 这个属性值,通过学习,我了解到:
strategy属性,提供四种值: GenerationType.AUTO: 主键由程序控制, 是默认选项 ,不设置就是这个 GenerationType.IDENTITY: 主键由数据库生成, 必须采用数据库自增长(否则dao层插入数据会报错), Oracle不支持这种方式 GenerationType.SEQUENCE: 通过数据库的序列产生主键, MYSQL不支持 GenerationType.Table: 提供特定的数据库产生主键, 该方式更有利于数据库的移植因此我们可以去掉 @GeneratedValue注解 , 我觉得这是最快捷的方法.
那么有人就会问了: 为什么我一开始要加 @GeneratedValue 注解呢?
这就涉及到了 @GeneratedValue 注解的作用了,这里我简单提一下:
@GeneratedValue注解可用于提供主键生成策略,例如数据库的主键自增是每次加1的,但是通过这个注解就可以修改了, 还有一些其他的作用,就等小伙伴们自己去发掘吧.
将 @GeneratedValue(strategy = GenerationType.IDENTITY) 去掉:
成功: