Я едва вижу любой указатель на следующей проблеме, связанной для Спящего режима. Это принадлежит реализации наследования с помощью таблицы единой базы данных с отношениями отцов и детей к себе. Например:
CREATE TABLE Employee (
empId BIGINT NOT NULL AUTO_INCREMENT,
empName VARCHAR(100) NOT NULL,
managerId BIGINT,
CONSTRAINT pk_employee PRIMARY KEY (empId)
)
Здесь, managerId столбец может быть пустым, или может указать на другую строку Списка сотрудников. Бизнес-правило требует, чтобы Сотрудник знал обо всем своем reportees и чтобы он знал о его менеджере. Бизнес-правила также позволяют строкам иметь пустой указатель managerId (у генерального директора организации нет менеджера).
Как мы отображаемся, эти отношения в В спящем режиме, стандарт many-one отношения не работает здесь? Особенно, если я хочу реализовать свои Объекты не только как соответствующий класс Объекта "Сотрудника", а скорее несколько классов, таких как "менеджер", "Помощник управляющего", "Инженер" и т.д., каждый наследовавшийся от "Сотрудника" супер класс объекта, некоторый объект, имеющий атрибуты, которые на самом деле не относятся ко всем, например, "менеджер" получает Льготы, другие не делают (соответствующий столбец таблицы принял бы пустой указатель, конечно).
Пример кода ценился бы (я намереваюсь использовать, в спящем режиме 3 аннотации).
Здесь вы выражаете две концепции:
Для реализации 1. вам необходимо использовать Hibernate одну таблицу для иерархии классов стратегию:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="emptype",
discriminatorType=DiscriminatorType.STRING
)
public abstract class Employee { ... }
@Entity
@DiscriminatorValue("MGR")
public class Manager extends Employee { ... }
Для реализации 2. вам нужно добавить две ассоциации с самореференцией на ] Сотрудник
:
Сотрудником
) В результате Сотрудник
может выглядеть так:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="emptype",
discriminatorType=DiscriminatorType.STRING
)
public abstract class Employee {
...
private Employee manager;
private Set<Employee> reportees = new HashSet<Employee>();
@ManyToOne(optional = true)
public Employee getManager() {
return manager;
}
@OneToMany
public Set<Employee> getReportees() {
return reportees;
}
...
}
В результате получатся следующие таблицы:
CREATE TABLE EMPLOYEE_EMPLOYEE (
EMPLOYEE_ID BIGINT NOT NULL,
REPORTEES_ID BIGINT NOT NULL
);
CREATE TABLE EMPLOYEE (
EMPTYPE VARCHAR(31) NOT NULL,
ID BIGINT NOT NULL,
NAME VARCHAR(255),
MANAGER_ID BIGINT
);
ALTER TABLE EMPLOYEE ADD CONSTRAINT SQL100311183749050 PRIMARY KEY (ID);
ALTER TABLE EMPLOYEE_EMPLOYEE ADD CONSTRAINT SQL100311183356150 PRIMARY KEY (EMPLOYEE_ID, REPORTEES_ID);
ALTER TABLE EMPLOYEE ADD CONSTRAINT FK4AFD4ACE7887BF92 FOREIGN KEY (MANAGER_ID)
REFERENCES EMPLOYEE (ID);
ALTER TABLE EMPLOYEE_EMPLOYEE ADD CONSTRAINT FKDFD1791F25AA2BE0 FOREIGN KEY (REPORTEES_ID)
REFERENCES EMPLOYEE (ID);
ALTER TABLE EMPLOYEE_EMPLOYEE ADD CONSTRAINT FKDFD1791F1A4AFCF1 FOREIGN KEY (EMPLOYEE_ID)
REFERENCES EMPLOYEE (ID);
Не уверен, что вы действительно хотите, но я думаю, что вам нужна таблица для иерархии классов
В этом случае каждая сущность сортируется с помощью DISCRIMINATOR_COLUMN следующим образом
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="EMPLOYEE_TYPE",
discriminatorType = DiscriminatorType.STRING
)
@DiscriminatorValue("EMPLOYEE")
public class Employee {
@Id @GeneratedValue
@Column(name="EMPLOYEE_ID")
private Integer id = null;
}
И его дочерние элементы отображаются в соответствии с
@Entity
@DiscriminatorValue("MANAGER")
public class Manager extends Employee {
// Manager properties goes here
...
}
. Чтобы проверить, давайте сделаем следующее
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
/*
insert
into
Employee
(EMPLOYEE_TYPE)
values
('EMPLOYEE')
*/
session.save(new Employee());
/*
insert
into
Employee
(EMPLOYEE_TYPE)
values
('MANAGER')
*/
session.save(new Manager());
session.clear();
session.close();
Но вместо наследования (которое вы можете увидеть много столбцов NULL из-за того, что несколько сущностей используют одну и ту же таблицу - при использовании InheritanceType.SINGLE_TABLE), ваша модель будет лучше, как показано ниже
@Entity
public class Employee {
private Employee manager;
private List<Employee> reporteeList = new ArrayList<Employee>();
/**
* optional=true
* because of an Employee could not have a Manager
* CEO, for instance, do not have a Manager
*/
@ManyToOne(optional=true)
public Employee getManager() {
return manager;
}
@OneToMany
public List<Employee> getReporteeList() {
return reporteeList;
}
}
Не стесняйтесь выбирать лучший подход, отвечающий вашим потребностям.
с уважением,
Большое спасибо, ребята. Я создал свою сущность «Сотрудник» следующим образом:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="EMPLOYEE_TYPE",
discriminatorType = DiscriminatorType.STRING
)
@DiscriminatorValue("Employee")
public abstract class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="EMPLOYEE_ID")
private Integer empId = null;
@Column(name="EMPLOYEE_NAME")
private String empName = null;
@Column(name="EMPLOYEE_SECRETARY")
private String secretary;
@Column(name="EMPLOYEE_PERKS")
private int perks;
@ManyToOne(targetEntity = Employee.class, optional=true)
@JoinColumn(name="MANAGER_ID", nullable=true)
private Employee manager = null;
@OneToMany
private Set<Employee> reportees = new HashSet<Employee>();
...
public Set<Employee> getReportees() {
return reportees;
}
}
Затем я добавил другие классы сущности без тела, а только значения столбцов Дискриминатора, такие как Manager, CEO и AsstManager. Я решил позволить Hibernate создать таблицу за меня. Ниже приводится основная программа:
SessionFactory sessionFactory = HibernateUtil.sessionFactory;
Session session = sessionFactory.openSession();
Transaction newTrans = session.beginTransaction();
CEO empCeo = new CEO();
empCeo.setEmpName("Mr CEO");
empCeo.setSecretary("Ms Lily");
Manager empMgr = new Manager();
empMgr.setEmpName("Mr Manager1");
empMgr.setPerks(1000);
empMgr.setManager(empCeo);
Manager empMgr1 = new Manager();
empMgr1.setEmpName("Mr Manager2");
empMgr1.setPerks(2000);
empMgr1.setManager(empCeo);
AsstManager asstMgr = new AsstManager();
asstMgr.setEmpName("Mr Asst Manager");
asstMgr.setManager(empMgr);
session.save(empCeo);
session.save(empMgr);
session.save(empMgr1);
session.save(asstMgr);
newTrans.commit();
System.out.println("Mr Manager1's manager is : "
+ empMgr.getManager().getEmpName());
System.out.println("CEO's manager is : " + empCeo.getManager());
System.out.println("Asst Manager's manager is : " + asstMgr.getManager());
System.out.println("Persons Reporting to CEO: " + empCeo.getReportees());
session.clear();
session.close();
Код работает нормально, Hibernate самостоятельно создавал столбец «MANAGER_EMPLOYEE_ID», в котором хранится FK. Я указал имя JoinColumn, чтобы сделать его «MANAGER_ID». Hibernate также создает таблицу EMPLOYEE_EMPLOYED, однако данные в ней не сохраняются.
Метод getReportees () возвращает значение null, в то время как getManager () работает нормально, как и ожидалось.