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. C#程序调用cmd执行命令(转)

    C#通过程序来调用cmd命令的操作 string str = Console.ReadLine(); System.Diagnostics.Process p = new System.Diagnos ...

  2. (转)webservice 测试窗体只能用于来自本地计算机的请求

    Question: WebService部署成站点之后,如果在本地测试webservice可以运行,在远程却显示“测试窗体只能用于来自本地计算机的请求”或者"The test form is ...

  3. .net Signalr 使用笔记

    官方参考地址:http://www.asp.net/signalr/overview/deployment/tutorial-signalr-self-host 1.服务器端可以是控制台.winfor ...

  4. static静态类与非静态类的区别

    static静态类与非静态类的区别 1.在非静态类中可以有实例成员也可以有静态成员 2.在调用的时候需要使用对像名.实例成员调用(先要实例化,如person ps=new person();  ps. ...

  5. js函数知识点

    1.即使写成functon a()也是可以调用外面定义的变量的,写(a,b),我估计是为了降低耦合性 2.即使写成function a()也是可以用arguments[a]来默认写了(a,b) 3.在 ...

  6. [Mugeda HTML5技术教程之11]Mugeda API简介

    一.API 概述 Mugeda API 提供了一个简单的,结构化的方法来实时动态管理Mugeda内容.它提供了一下方法: •访问Mugeda内容中的对象. •获取和设置对象属性,如位置.旋转.比例.不 ...

  7. php基础之三 数组

    一.正则表达式: 1. "/"代表界定符, "^"代表开始符号 "&"结束符号 eg:   $reg="/(13[0-9] ...

  8. JQuery实现隔行变色和突出显示当前行 效果

    运行效果如下图: jquery关键代码: <script type="text/javascript"> //该文件为:js.js // 当鼠标移到表格上是,当前一行背 ...

  9. Flask学习记录之Flask-Migrate

    一.配置Flask-Migrate from flask.ext.migrate import Migrate, MigrateCommand migrate = Migrate(app,db) #第 ...

  10. Swift--存储属性-备

    Swift中的属性分为存储属性和计算属性,存储属性就是Objective-C中的数据成员,计算属性不存储数据,但可以通过计算其他属性返回数据. 存储属性可以存储数据,分为常量属性(用关键字let定义) ...