在getId()方法添加@Id注解导致自增ID列抛出异常的原因
为何在getId()方法上添加@Id注解时,自增ID列会抛出异常?
报错信息
Type Exception Report Message Converting `org.hibernate.id.IdentifierGenerationException` to JPA `PersistenceException` : ids for this class must be manually assigned before calling save(): models.User Description The server encountered an unexpected condition that prevented it from fulfilling the request. Exception jakarta.persistence.PersistenceException: Converting `org.hibernate.id.IdentifierGenerationException` to JPA `PersistenceException` : ids for this class must be manually assigned before calling save(): models.User org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:165) org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:175) org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:182) org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:741) org.hibernate.internal.SessionImpl.persist(SessionImpl.java:719) servlets.Authentication.doGet(Authentication.java:30) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:668) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:777) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) Root Cause org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): models.User org.hibernate.id.Assigned.generate(Assigned.java:33) org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:114) org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:184) org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:129) org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:53) org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:735) org.hibernate.internal.SessionImpl.persist(SessionImpl.java:719) servlets.Authentication.doGet(Authentication.java:30) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:668) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:777) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
实体类代码
package models; import jakarta.persistence.*; import java.sql.Date; @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", updatable = false, nullable = false) private int id; @Column(name = "nome", nullable = false) private String nome; @Column(name = "cognome", nullable = false) private String cognome; @Column(name = "mail", nullable = false) private String mail; @Column(name = "password", nullable = false) private String password; @Column(name = "token", nullable = true) private String token; @Column(name = "dataCreazioneToken", nullable = true) private Date dataCreazioneToken; public User() {} public User(String nome, String cognome, String mail, String password) { this.nome = nome; this.cognome = cognome; this.mail = mail; this.password = password; } public Date getDataCreazioneToken() { return dataCreazioneToken; } public void setDataCreazioneToken(Date creazioneToken) { this.dataCreazioneToken = creazioneToken; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getCognome() { return cognome; } public void setCognome(String cognome) { this.cognome = cognome; } public String getMail() { return mail; } public void setMail(String mail) { this.mail = mail; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public void setId (int id) { this.id = id; } @Id public int getId() { return id; } }
问题现象
移除getId()方法上的@Id注解后,异常不再出现,ID可正常自动生成,无法理解该现象的原因。
原因解析
JPA(以Hibernate为实现)有两种属性访问策略:字段访问和方法访问,单个实体类只能二选一,不能混用。
- 你在
id字段上添加了@Id和@GeneratedValue(strategy = GenerationType.IDENTITY),这属于字段访问策略,明确告诉Hibernate该字段是主键,且由数据库自动生成值。 - 但你又在
getId()方法上重复添加@Id注解,这会让Hibernate优先采用方法访问策略。此时方法上的@Id没有搭配@GeneratedValue,Hibernate会默认使用Assigned生成策略——要求开发者手动为ID赋值,否则就抛出ids for this class must be manually assigned before calling save()异常。 - 移除方法上的
@Id后,Hibernate回到字段访问策略,遵循字段上的@GeneratedValue配置,让数据库自动生成ID,因此异常消失。
解决方案
保持实体类的访问策略一致:要么所有注解都加在字段上,要么都加在对应的getter方法上。比如保留字段上的@Id和@GeneratedValue,删除方法上的@Id即可。
内容的提问来源于stack exchange,提问作者hamza
相关产品推荐
相关产品推荐

