Recently I was working on a hibernate project and I have added few entity beans, when executed I got below exception stack trace.
Initial SessionFactory creation failed.org.hibernate.AnnotationException: No identifier specified for entity: com.journaldev.hibernate.model.Address
org.hibernate.AnnotationException: No identifier specified for entity: com.journaldev.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.journaldev.hibernate.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:22)
at com.journaldev.hibernate.util.HibernateUtil.getSessionFactory(HibernateUtil.java:34)
at com.journaldev.hibernate.main.HibernateExample.main(HibernateExample.java:15)
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.journaldev.hibernate.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:29)
at com.journaldev.hibernate.util.HibernateUtil.getSessionFactory(HibernateUtil.java:34)
at com.journaldev.hibernate.main.HibernateExample.main(HibernateExample.java:15)
The issue was coming because I forgot to specify primary key in my Entity bean, my bean was defined as;
Address.java
package com.journaldev.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;
}
}
All I needed to fix the issue was to annotate the primary key field with @Id
annotation. I changed my id field declaration to below and issue was resolved.
@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;
This is an easy fix but there is one scenario where it becomes more confusing. Usually hibernate automatically figures out the way to access the bean properties based on the annotations used on variable or getter-setter. However, We can explicitly define access type for our entity beans. There are two types of access types:
- Field: Hibernate will look for annotations on variables in this case, like we have defined for Address class above as
@Access(value=AccessType.FIELD)
. - Property: Hibernate will look for annotations on getter-setter methods in this case, syntax for this is
@Access(value=AccessType.PROPERTY)
If the annotations are not defined as per access type, then also we will get this exception. For example if the access type is property and we have added all the annotations on bean variables, we will get this exception.
A sample class that will throw this exception is given below.
Employee.java
package com.journaldev.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 + "}";
}
}
Notice that all the JPA annotations are used with getter methods whereas access type is defined as Field, just change the access type to property to solve this issue.
I don’t understand the sense of the @Access.
I have this options:
use no @Access
– and set @Id before my variables, so I have direct access without setters
– and set @Id before my setters, so I have access with setters
This works fine.
Now I want to use @Access(AccessType.PROPERTY) but set the @Id before my variables and I get this error.
I have to put the @Id before the setters but why should I use the @Access annotation?
It does the same and didn’t overwrite the setting.
Thanks brother.Faced the same problem and tried a lot to solve it and finally was able to do so by visiting this webpage.
Thank you very much Pankaj. I was stuck with this issue for hours and finally figured it out here. You are a lifesaver.
Hi Pankaj
I tried using both AccessType.FIELD and AccessType.PROPERTY in Hibernate Core {5.4.10.Final} but getting same error.
Hi ,
Is it possible to add the user defined sequence to the id, in this concept.
Thanks
Murali.K
I Got the exception in Hibernate 4 (4.3.10.Final)
Caused by: org.hibernate.AnnotationException: No identifier specified for entity
Solution :
My Entity class was mapped only for ready only data.
So I changed to @Embeddable annotaion instead of @Entity annotation.
@Embeddable
//@Entity
@Table(name=”geonames”)
public class Geoname implements Serializable {
//no PK. or embedded key
private String name;
private String street;
}
Hi Pankaj,
Can you please tell how to configure id column if I’m doing XML configuration instead of annotations?
Thanks mate, this was precisely my problem, great explanation to a not-so-easy-to-trace problem.
Nice article. Thanks!