Estoy tratando de crear una aplicación que reciba el archivo XML con la lista de Empleados y almacene la relación padre-hijo / empleado-gerente en la tabla de base de datos única.

Mi archivo XML se parece a este:

<Employees>
    <Employee manager="Patrick">Martin</Employee>
    <Employee manager="Patrick">Kent</Employee>
    <Employee manager="Martin">Mark</Employee>
    <Employee>Hugo</Employee> <!-- root element of the employee-manager tree -->
    <Employee manager="Hugo">Osa</Employee>
    <Employee manager="Osa">Patrick</Employee>
</Employee>

Un empleado puede tener solo un gerente, pero un gerente puede tener múltiples subordinados / empleados.

No tengo problemas al desarmar el archivo XML recibido, pero ahora estoy tratando de crear el modelo apropiado que me permita almacenar los valores desarmados en la base de datos. Los datos deben almacenarse en la tabla denominada "Empleado" y deben contener los siguientes datos:

------------------------------
| id            | Integer    |
------------------------------
| employee_name | String     |
------------------------------
| parent_id     | Integer    | -- reference to the manager
------------------------------

Creé una nueva clase llamada Employee pero no estoy seguro de cómo definir las anotaciones ManyToOne / OneToMany apropiadas.

Como soy bastante nuevo en esto, busqué en Google un par de ejemplos y tutoriales (así como las respuestas a las preguntas similares aquí en Stack Overflow), pero creo que estoy cometiendo un gran error en esta implementación al definir esto modelo. Mi último intento se ve así:

public class Employee {
    @Id
    @GeneratedValue
    private int id;

    @Column(name = "parent_id")
    @Transient
    @ManyToOne(cascade={CascadeType.ALL})
    private String managerName;

    @Column(name = "employee_name")
    @JoinColumn(name="parent_id")
    private String employeeName;

    // getters and setters

Si alguien pudiera señalarme en la dirección de definir el modelo apropiado, ¡sería muy, muy apreciado!

1
hezus 4 abr. 2017 a las 11:05

2 respuestas

La mejor respuesta

En Hibernate cuando desea asignar una relación ManyToOne, la asigna entre entidades y no solo propiedades, por lo que debe hacer referencia a un objeto de tipo Employee y no solo a {{X3} } o un id.

Problemas:

  • Entonces su mapeo es incorrecto y arrojará muchos errores de mapeo, en lugar de escribir:

    @Column(name = "parent_id")
    @Transient
    @ManyToOne(cascade={CascadeType.ALL})
    private String managerName;
    

    Necesita mapear la relación ManyToOne de esta manera:

    @ManyToOne(cascade={CascadeType.ALL})
    @JoinColumn(name="manager_id")
    private Employee manager;
    
  • Y asegúrese de mapear el otro lado de la relación de esta manera:

    @OneToMany(mappedBy="manager")
    private Set<Employee> subordinates = new HashSet<Employee>();
    
  • Además, su asignación para la columna employee_name es incorrecta, el @JoinColumn solo se usa para relaciones y no se puede usar con un columna simple, debe escribirla así:

    @Column(name = "employee_name")
    private String employeeName;
    
  • El @Transient es inútil en su mapeo, solo lo usamos si desea utilizar un atributo que no se conservará en la base de datos.

  • Y lo más importante asegúrese de asignar su clase con @Entity, para que pueda ser persistió en la base de datos.

Ejemplo:

Puede consultar Hibernate Self Join Annotations One Para muchos ejemplos de mapeo usa el mismo modelo que desea implementar.

2
cнŝdk 4 abr. 2017 a las 08:57

Simplemente debe tener una relación ManyToOne con su tabla de empleados, es decir, varios empleados pueden tener el mismo administrador (que también es un empleado) y para el administrador este campo permanecerá vacío, como este:

@Entity
@Table(name = "EMPLOYEE")
public class Employee {

    @Id
    @GeneratedValue
    private int id;

    @ManyToOne
    private Employee manager;

    @Column(name = "employee_name")
    private String employeeName;
-1
Bartha Barna 4 abr. 2017 a las 11:06