author: hiu

更正说明:今天(2014-07-07)才发现的问题,我把@Id设置在了实体类中的id中,@Id是主键,应该设置在实体类的keyjobno中,之前发的文章可能误导了大家,如今更正一下,请看以下红色的更正内容。



近期由ibatis转用Hibernate,期间遇到了一系列的问题,今天又遇到了个问题,是由于自增列的问题导致保存时报错,如今记录下来,以便日后忘记时查看

这个问题事实上是使用myEclipse生成表的实体类时,自增列的注解错误导致的。

问题原因:利用myEclipse的Hibernate Reverse Engineening生成的实体类自增列注解设置了在主键keyjobno上,而不是相应的 id 列上

解决的方法 :将自增列注解设置在相应的 自增列id上

数据库employee表:

这里主要列出了部分字段,关键在于id和keyjobno,id设置了是自增列,keyjobno设置为主键

利用myEclipse的Hibernate Reverse Engineening生成实体类

生成后的实体类Employee,仅仅贴出了keyjobno,id的,其他的没贴出来

@Entity
@Table(name = "employee", catalog = "union_ssh", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
public class Employee implements java.io.Serializable { // Fields private String keyjobno;
private Integer id; @Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "keyjobno", unique = true, nullable = false, length = 20)
public String getKeyjobno() {
return this.keyjobno;
} public void setKeyjobno(String keyjobno) {
this.keyjobno = keyjobno;
} @Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
} public void setId(Integer id) {
this.id = id;
}
}

service层

public Employee save(Employee employee) throws SQLException {

      employee.setKeyjobno("K8888");

      employeeDao.save(employee);

      return employee;
}

dao层

@Override
public Serializable save(T o) {
return this.getCurrentSession().save(o);
}

控制台打印出的sql语句:

2014-07-04 14:10:50 [org.hibernate.SQL]-[DEBUG]
insert
into
union_ssh.employee
(born_boon, borndate, company, createdate, dept, getborn_date, getmarry_date, id, identitycard, ifout, interest, jobno, lodging, marry, marry_boon, name, nativename, operator, phone, politicsface, sex)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
union_ssh.employee
(born_boon, borndate, company, createdate, dept, getborn_date, getmarry_date, id, identitycard, ifout, interest, jobno, lodging, marry, marry_boon, name, nativename, operator, phone, politicsface, sex)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2014-07-04 14:10:50 [org.hibernate.engine.jdbc.spi.SqlExceptionHelper]-[DEBUG] Field 'keyjobno' doesn't have a default value [n/a]
<span style="color:#ff0000;"><strong>java.sql.SQLException: Field 'keyjobno' doesn't have a default value</strong></span>

注意红色部分了,报错说我keyjobno没有默认值,最奇怪的就是这里了,我明明在service层里设置了

employee.setKeyjobno("K8888");

明明已经为keyjobno设置值了,竟然还说我没有默认值。再看一下打出来的sql语句,里面有id,可是没有keyjobno,按理说id在数据库表中设置了自增,这里不应该也插入的,但keyjobno明明是已经设置了值的,却没有显示在插入的sql中,这是由于注解时将keyjobno设置为了自增列了。

如今再来看看实体类中的注解:

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "keyjobno", unique = true, nullable = false, length = 20)
public String getKeyjobno() {
return this.keyjobno;
}

注解意思:

@Id —— 注解声明了该实体bean的标识属性(相应表中的主键)。

@GeneratedValue —— 注解声明了主键的生成策略。该注解有例如以下属性

strategy
指定生成的策略(JPA定义的),这是一个GenerationType。默认是GenerationType. AUTO   

   GenerationType.AUTO 主键由程序控制

GenerationType.IDENTITY
主键由数据库自己主动生成(主要是自己主动增长类型)

看到注讲解明,大家应该就明确了,我在数据库表中设置的是id自增列,可是生成的实体类的自增列却是keyjobno,这就是导致保存失败的原因了,将实体类改为下面形式,主要是将keyjobno的自增注解剪切到id列中

@Entity
@Table(name = "employee", catalog = "union_ssh", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
public class Employee implements java.io.Serializable { private String keyjobno;
private Integer id; @Column(name = "keyjobno", unique = true, nullable = false, length = 20)
public String getKeyjobno() {
return this.keyjobno;
} public void setKeyjobno(String keyjobno) {
this.keyjobno = keyjobno;
} @Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
} public void setId(Integer id) {
this.id = id;
}
}

@Id设置了在id属性的get方法中,去掉这里的@Id,由于@Id是代表主键,能够看到上面数据库employee表中的图,keyjobno才是主键,所以应该把@Id设置在keyjobno的get方法上才对

@Id
@Column(name = "keyjobno", unique = true, nullable = false, length = 20)
public String getKeyjobno() {
return this.keyjobno;
}

假设你不更正这里,在做employee表的单独插入操作时是没问题的,假设你有其他表关联了employee表的keyjobno主键,但你没有将@Id设置在keyjobno上,那么这里问题就来了,假设你往关联的表中插入数据时,就无法插入了,由于关联的表相应不了employee的主键,导致无法插入。我今天用in_union_his表关联了employee表,在做in_union_his表插入操作时,不断提示外键约束失败,无法往子表in_union_his中插入数据

,以下是我今天操作时失败的错误信息:Cannot add or update a child row: a foreign key constraint fails

2014-07-07 10:03:18 [org.hibernate.SQL]-[DEBUG]
insert
into
union_ssh.employee
(bornboon, borndate, company, createdate, dept, getborndate, getmarrydate, identitycard, ifout, interest, jobno, keyjobno, lodging, marry, marryboon, name, nativename, operator, phone, politicsface, sex)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
union_ssh.employee
(bornboon, borndate, company, createdate, dept, getborndate, getmarrydate, identitycard, ifout, interest, jobno, keyjobno, lodging, marry, marryboon, name, nativename, operator, phone, politicsface, sex)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2014-07-07 10:03:18 [org.hibernate.id.IdentifierGeneratorHelper]-[DEBUG] Natively generated identity: 660
2014-07-07 10:03:18 [org.hibernate.engine.spi.ActionQueue]-[DEBUG] Executing identity-insert immediately
2014-07-07 10:03:18 [org.hibernate.SQL]-[DEBUG]
insert
into
union_ssh.in_union_his
(createdate, keyjobno, inuniondate, operator)
values
(?, ?, ?, ?)
Hibernate:
insert
into
union_ssh.in_union_his
(createdate, keyjobno, inuniondate, operator)
values
(?, ?, ?, ?)
2014-07-07 10:03:18 [org.hibernate.engine.jdbc.spi.SqlExceptionHelper]-[DEBUG]Cannot add or update a child row: a foreign key constraint fails (`union_ssh`.`in_union_his`, CONSTRAINT `FK_in_union_his` FOREIGN KEY (`keyjobno`) REFERENCES `employee` (`keyjobno`) ON DELETE CASCADE ON UPDATE CASCADE) [n/a]
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`union_ssh`.`in_union_his`, CONSTRAINT `FK_in_union_his` FOREIGN KEY (`keyjobno`) REFERENCES `employee` (`keyjobno`) ON DELETE CASCADE ON UPDATE CASCADE)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

仅仅要将@Id设在数据库表主键相应的实体类的属性keyjobno上,就攻克了,关键是我之前把@Id设置在了id属性上。

又一次部署,再运行保存,控制台打印出来的sql语句:

2014-07-04 14:30:21 [org.hibernate.SQL]-[DEBUG]
insert
into
union_ssh.employee
(born_boon, borndate, company, createdate, dept, getborn_date, getmarry_date, identitycard, ifout, interest, jobno, keyjobno, lodging, marry, marry_boon, name, nativename, operator, phone, politicsface, sex)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
union_ssh.employee
(born_boon, borndate, company, createdate, dept, getborn_date, getmarry_date, identitycard, ifout, interest, jobno, keyjobno, lodging, marry, marry_boon, name, nativename, operator, phone, politicsface, sex)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2014-07-04 14:30:21 [org.hibernate.id.IdentifierGeneratorHelper]-[DEBUG] Natively generated identity: 557

最后 一行Natively generated identity: 557这句是什么意思呢,事实上557就是插入的这条记录的id了,由于我数据库中已经有556记录了,这就说明保存成功了,大家能够看到,这条sql语句已经没有id存了,也即是说sql语句插入时没有把id插入,而是在数据库中自己主动添加�了。今天(2014-07-07)再经过測试,发现,这里显示不显示id出来都能够插入成功,不显示的原因是由于我之前把注解@Id,@GeneratedValue(strategy
= IDENTITY)设在了id列中才没显示出来,我预计是仅仅要你注解设置在自增列而且自增列是主键时,就在插入时sql语句不显示这个列了

总结:注解地方的错误是由于使用myEclipse生成实体类时引致的注解设置地方错误,所以有时也不要太过依赖自己主动生成实体类。个人推測原因,是由于我将id设为是自增的,但keyjobno列设置为主键,也即是说,这两列都是唯一的,myEclipse在生成实体类是可能不能区分,就将自增列的注解设置了在主键的列上了,没细致研究,大家有兴趣的话,能够去研究下。

Hibernate自增列保存失败的问题的更多相关文章

  1. Hibernate一对多关联关系保存时的探究

    在以前使用hibernate时,经常对保存存在关联关系的对象时,不确定是否能保存成功.    因此,特意对一对多关系的2个对象进行实践. 一.pojo类和配置文件的准备         这里有一点提前 ...

  2. MySQL--更新自增列的潜在风险

    ##=====================================================================##测试环境:MySQL版本:MySQL 5.7.19复制 ...

  3. MySQL使用AUTO_INCREMENT列的表注意事项之update自增列篇

    1)对于MyISAM表,如果用UPDATE更新自增列,如果列值与已有的值重复,则会出错:如果大于已有的最大值,则会自动更新表的AUTO_INCREMENT,操作是安全的. (2)对于innodb表,u ...

  4. mysql 清空或删除表数据后,控制表自增列值的方法

    http://blog.sina.com.cn/s/blog_68431a3b0100y04v.html 方法1: truncate table 你的表名 //这样不但将数据全部删除,而且重新定位自增 ...

  5. mysql 深度解析auto-increment自增列"Duliplicate key"问题

    转载自:https://cloud.tencent.com/developer/article/1367681 问题描述 近期,线上有个重要Mysql客户的表在从5.6升级到5.7后master上插入 ...

  6. innodb 自增列重复值问题

    1 innodb 自增列出现重复值的问题 先从问题入手,重现下这个bug use test; drop table t1; create table t1(id int auto_increment, ...

  7. SQL Server数据库sql语句生成器(SqlDataToScript)的使用(sql server自增列(id)插入固定值)

    SqlDataToScript是根据表数据进行生成 Insert Into语句,此工具还有一个好处是可以对自增列插入固定值,例如:自增的列id值为5,但是5这个行值已经删除,如果想存储Id自增列值为5 ...

  8. SQL Server 2008 R2——使用计算列为表创建自定义的自增列

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  请通过右侧公告中的“联系邮 ...

  9. mysql中,通过脚本设置表的自增列,及自增步长

    设置自增列(其实通过navicate可以直接设置的,也方便:要不然可能需要删除列了) ALTER TABLE `domain_dns_tucows` CHANGE `id` `id` INT(11) ...

随机推荐

  1. 【转】IOS缓存机制详解

    人魔七七:http://www.cnblogs.com/qiqibo/ 为什么要有缓存 应用需要离线工作的主要原因就是改善应用所表现出的性能.将应用内容缓存起来就可以支持离线.我们可以用两种不同的缓存 ...

  2. 网页JavaScript

    用法. JavaScript一般用于 head , body , </html> 之后. 格式<script language="javascript"> ...

  3. FreeMarker辅助

    /** * FreeMarker 辅助类 * @author Rubekid * */ public class FreeMarkerHelper { /** * 模板文件存放目录 */ privat ...

  4. 关于this的指向问题

    一个关于this指向而引发的血案... 在测试this指向的程序中,我写错了id对象,结果呢,居然也有效果,这真是超于我意料之外太多了,我以为自己写错了,结果一样可以用....... <div ...

  5. 2:url有规律的多页面爬取

    举例网站:http://www.luoo.net/music/期刊号 e.g:http://www.luoo.net/music/760 打算爬取其title:Hello World:pic:desc ...

  6. (转)js 中{},[]中括号,大括号使用详解

    一.{ } 大括号,表示定义一个对象,大部分情况下要有成对的属性和值,或是函数. 如:var LangShen = {"Name":"Langshen",&qu ...

  7. Asp.Net--上传大文件(页面超时)

    几个方法: 修改文件上传大小的限制 以文件形式保存到服务器 转换成二进制字节流保存到数据库 将二进制通过循环的方式写入磁盘 一.修改文件上传大小的限制 通过对web.config和machine.co ...

  8. 解决表格里面使用text-overflow后依旧不能隐藏超出的文本

    解决表格里面使用text-overflow后依旧不能隐藏超出的文本 来源: http://blog.csdn.net/colinmuxi/article/details/9069595  (非原创,自 ...

  9. memcached学习笔记——存储命令源码分析上篇

    原创文章,转载请标明,谢谢. 上一篇分析过memcached的连接模型,了解memcached是如何高效处理客户端连接,这一篇分析memcached源码中的process_update_command ...

  10. C程序设计语言练习题1-10

    练习1-10 编写一个将输入复制到输出的程序,并将起重的制表符替换为\t,把回退符替换成\b,把反斜杠替换为\\.这样可以将制表符和回退符以可见的方式显示出来. 代码如下: #include < ...