org.hibernate.AnnotationException:未为实体类指定标识符
时间:2020-02-23 14:34:41 来源:igfitidea点击:
最近,我正在一个休眠项目中,我添加了几个实体bean,执行时得到了异常堆栈跟踪以下的信息。
Initial SessionFactory creation failed.org.hibernate.AnnotationException: No identifier specified for entity: com.theitroad.hibernate.model.Address org.hibernate.AnnotationException: No identifier specified for entity: com.theitroad.hibernate.model.Address at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:277) at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:224) at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:775) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3788) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3742) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844) at com.theitroad.hibernate.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:22) at com.theitroad.hibernate.util.HibernateUtil.getSessionFactory(HibernateUtil.java:34) at com.theitroad.hibernate.main.HibernateExample.main(HibernateExample.java:15) Exception in thread "main" java.lang.ExceptionInInitializerError at com.theitroad.hibernate.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:29) at com.theitroad.hibernate.util.HibernateUtil.getSessionFactory(HibernateUtil.java:34) at com.theitroad.hibernate.main.HibernateExample.main(HibernateExample.java:15)
因为我忘记在Entity bean中指定主键,所以问题来了,我的bean被定义为;
Address.java
package com.theitroad.hibernate.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Parameter; @Entity @Table(name = "ADDRESS") @Access(value=AccessType.FIELD) public class Address { @Column(name = "emp_id", unique = true, nullable = false) @GeneratedValue(generator = "gen") @GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") }) private long id; @Column(name = "address_line1") private String addressLine1; @Column(name = "zipcode") private String zipcode; @Column(name = "city") private String city; @OneToOne @PrimaryKeyJoinColumn private Employee employee; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAddressLine1() { return addressLine1; } public void setAddressLine1(String addressLine1) { this.addressLine1 = addressLine1; } public String getZipcode() { return zipcode; } public void setZipcode(String zipcode) { this.zipcode = zipcode; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } @Override public String toString() { return "AddressLine1= " + addressLine1 + ", City=" + city + ", Zipcode=" + zipcode; } }
我需要解决的所有问题是使用@ Id
注释对主键字段进行注释。
我将ID字段声明更改为以下内容,问题已解决。
@Id @Column(name = "emp_id", unique = true, nullable = false) @GeneratedValue(generator = "gen") @GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") }) private long id;
这是一个简单的解决方法,但是在某些情况下它变得更加令人困惑。
通常,hibernate根据变量或者getter-setter上使用的注释自动找出访问Bean属性的方法。
但是,我们可以为实体bean明确定义访问类型。
访问类型有两种:
领域:在这种情况下,Hibernate将在变量上寻找注释,就像我们在上面为Address类定义为@Access(value = AccessType.FIELD)一样。
属性:在这种情况下,Hibernate将在getter-setter方法上寻找注释,其语法为@Access(value = AccessType.PROPERTY)。
如果注释未按访问类型定义,那么我们也将获得此异常。
例如,如果访问类型是属性,并且我们已在bean变量上添加了所有注释,则将获得此异常。
下面给出了将引发此异常的示例类。
Employee.java
package com.theitroad.hibernate.model; import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Table; import org.hibernate.annotations.Cascade; @Entity @Table(name = "EMPLOYEE") @Access(value=AccessType.FIELD) public class Employee { private long id; private String name; private double salary; private Address address; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "emp_id") public long getId() { return id; } public void setId(long id) { this.id = id; } @OneToOne(mappedBy = "employee") @Cascade(value = org.hibernate.annotations.CascadeType.ALL) public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Column(name = "emp_name") public String getName() { System.out.println("Employee getName called"); return name; } public void setName(String name) { System.out.println("Employee setName called"); this.name = name; } @Column(name = "emp_salary") public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } @Override public String toString() { return "Id= " + id + ", Name= " + name + ", Salary= " + salary + ", {Address= " + address + "}"; } }
注意,所有JPA批注都与getter方法一起使用,而访问类型定义为Field,只需将访问类型更改为property即可解决此问题。