首页 > 代码库 > Hibernate自增列保存失败的问题
Hibernate自增列保存失败的问题
author: hiu
最近由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() { <span style="white-space:pre"> </span>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; } <strong>@Id @GeneratedValue(strategy = IDENTITY)</strong> @Column(name = "id", unique = true, nullable = false) public Integer getId() { return this.id; } public void setId(Integer id) { this.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插入,而是在数据库中自动增加了。
总结:注解地方的错误是因为使用myEclipse生成实体类时引致的注解设置地方错误,所以有时也不要太过依赖自动生成实体类。个人猜测原因,是因为我将id设为是自增的,但keyjobno列设置为主键,也即是说,这两列都是唯一的,myEclipse在生成实体类是可能不能区分,就将自增列的注解设置了在主键的列上了,没仔细研究,大家有兴趣的话,可以去研究下。