Trang chủHướng dẫnHướng dẫn fix lỗi Hibernate AnnotationException: No identifier specified for entity Class
Fix Bug

Hướng dẫn fix lỗi Hibernate AnnotationException: No identifier specified for entity Class

CyStack blog 3 phút để đọc
CyStack blog22/08/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 3 minutes

Khám phá nguyên nhân và cách khắc phục lỗi Hibernate AnnotationException. Hướng dẫn chi tiết giúp bạn xử lý lỗi annotation hiệu quả trong Hibernate.

fix lỗi Hibernate AnnotationException

 

Gần đây, khi tôi làm việc trên một dự án Hibernate và thêm một vài entity bean, lúc chạy chương trình tôi đã gặp thông báo exception stack trace như dưới đây.

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)

Nguyên nhân dẫn đến lỗi trên là do tôi quên khai báo primary key trong Entity bean. Bean của tôi được định nghĩa như sau: 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;
	}
}

Tất cả những gì mình cần làm để khắc phục lỗi là thêm annotation @Id cho trường primary key. Mình đã sửa phần khai báo trường id như dưới đây và lỗi đã được giải quyết:

@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;

Đây là một lỗi dễ khắc phục, nhưng có một trường hợp khiến nó trở nên rắc rối hơn. Thông thường, Hibernate sẽ tự động xác định cách truy cập các thuộc tính của bean dựa trên việc bạn đặt annotation ở biến hoặc getter/setter. Tuy nhiên, chúng ta cũng có thể chỉ định rõ ràng kiểu truy cập cho entity bean. Có hai kiểu truy cập chính:

  1. Field: Hibernate sẽ tìm kiếm chú thích trên các biến trong trường hợp này, giống như chúng ta đã định nghĩa cho lớp Địa chỉ ở trên là @Access(value=AccessType.FIELD).
  2. Property: Hibernate sẽ tìm kiếm chú thích trên các phương thức getter-setter trong trường hợp này, cú pháp cho việc này là @Access(value=AccessType.PROPERTY)

Nếu các annotation không được khai báo đúng với kiểu truy cập đã định, bạn cũng sẽ gặp exception này. Ví dụ: nếu kiểu truy cập là Property nhưng tất cả annotation lại đặt trên biến, Hibernate sẽ báo lỗi. Dưới đây là một ví dụ class Employee.java sẽ gây ra exception này.

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 + "}";
	}

}

Hãy để ý rằng tất cả các annotation JPA đều được đặt trên các phương thức getter, trong khi access type lại được khai báo là Field. Chỉ cần đổi access type thành Property là sẽ giải quyết được vấn đề này.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất