[تم الحل] org.hibernate.AnnotationException: لم يتم تحديد هوية لفئة الكيان

مؤخرًا كنت أعمل على مشروع هيبرنيت، وقمت بإضافة بعض كائنات الكيان، عند تنفيذها حصلت على سلسلة استثناء كما يلي:

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)

كانت المشكلة تنشأ لأنني نسيت تحديد المفتاح الأساسي في كائن الكيان الخاص بي، تم تعريف كائني كما يلي: 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;
	}
}

كل ما كنت بحاجة لفعله لحل المشكلة كان تعليق الحقل الرئيسي بتعليق @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;

هذا حلاً سهلاً ولكن هناك سيناريو واحد يصبح فيه الأمر أكثر تعقيدًا. عادةً ما يحدد هيبرنيت طريقة الوصول إلى خصائص الكائن بناءً على التعليقات المستخدمة على المتغير أو المنشئ-المحدد. ومع ذلك، يمكننا تحديد نوع الوصول بوضوح لكائنات الكيان الخاصة بنا. هناك نوعان من أنواع الوصول:

  1. Field: سيبحث هيبرنيت عن التعليقات على المتغيرات في هذه الحالة، مثلما قمنا بتعريفها لفئة العنوان أعلاه كما في @Access(value=AccessType.FIELD).
  2. Property: سيبحث هيبرنيت عن التعليقات على طرق المنشئ-المحدد في هذه الحالة، الصيغة لهذا هي @Access(value=AccessType.PROPERTY)

إذا لم يتم تحديد التعليقات وفقًا لنوع الوصول، فسوف نحصل أيضًا على هذا الاستثناء. على سبيل المثال إذا كان نوع الوصول هو الخاصية وقمنا بإضافة جميع التعليقات على متغيرات الكائن، فسوف نحصل على هذا الاستثناء. الفئة العينية التي ستثير هذا الاستثناء معطاة أدناه. 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 + "}";
	}

}

لاحظ أن جميع التعليقات JPA تستخدم مع طرق المنشئ-المحدد بينما يتم تحديد نوع الوصول كحقل، قم بتغيير نوع الوصول إلى خاصية لحل هذه المشكلة.

Source:
https://www.digitalocean.com/community/tutorials/solved-org-hibernate-annotationexception-no-identifier-specified-for-entity-class