主键默认值报错:java.sql.SQLException: Field ‘id‘ doesn‘t have a default value

问题现象:

今天在调用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) 去掉:

 
 

成功:

猜你喜欢

转载自blog.csdn.net/weixin_42585386/article/details/109203750
今日推荐