3.1 Mapeamento de entidades dependentes

No SQL, você pode escrever consultas usando JOIN. É possível fazer o mesmo em HQL? A resposta curta é sim. Mas a resposta completa será mais interessante.

Primeiro, quando escrevemos um JOIN em SQL, geralmente significa que uma tabela se refere a outra tabela. Por exemplo, a tabela de tarefas contém uma coluna employee_id que se refere à coluna id da tabela de funcionários.

Essa dependência pode ser descrita usando anotações no Hibernate. Primeiro, vamos apenas criar Entidades para nossas tabelas. Primeiro, vamos descrever a tabela de funcionários:

@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @Column(name="salary")
   public Integer salary;

   @Column(name="join_date")
   public Date joinDate;
}

E a classe EmployeeTask para a tabela de tarefas :

@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @Column(name="employee_id")
   public Integer employeeId;

   @Column(name="deadline")
   public Date deadline;
}

Está tudo bem, mas há uma sugestão. Vejamos o campo employeeId no último exemplo:

@Column(name="employee_id")
public Integer employeeId;

Você percebe algo estranho? Caso contrário, isso significa que você já formou uma maneira de pensar na linguagem SQL.

O fato é que na linguagem Java geralmente descrevemos essa dependência de maneira um pouco diferente:

public Employee employee;

Não precisamos especificar um id , geralmente apenas especificamos uma variável que contém uma referência ao objeto Employee . Ou armazena nulo se não houver tal objeto.

E o Hibernate nos permite descrever tal situação usando anotações:

@ManyToOne
@JoinColumn(name="employee_id", nullable=true)
public Employee employee;

A anotação @ManyToOneinforma ao Hibernate que muitas entidades EmployeeTask podem se referir a uma entidade Employee .

E a anotação @JoinColumnespecifica o nome da coluna da qual o id será obtido . Todas as outras informações necessárias serão retiradas das anotações da classe Employee.

O resultado final ficará assim:

@Entity
@Table(name="task")
class EmployeeTask
{
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @ManyToOne
   @JoinColumn(name="employee_id", nullable=true)
   public Employee employee;

   @Column(name="deadline")
   public Date deadline;
}

3.2 Usando join em HQL

E agora vamos ver como escrever consultas para entidades relacionadas em HQL.

Primeira situação.

Temos um funcionário (Employee) e queremos obter uma lista de suas tarefas. Veja como essa consulta ficaria em SQL:

SELECT task.* FROM task JOIN employee ON task.employee_id = employee.id
WHERE employee.name = "Ivan Ivanovich";

E agora vamos escrever a mesma consulta em HQL:

from EmployeeTask where employee.name = "Ivan Ivanovich"

A classe EmployeeTask tem um campo de funcionário e tem um campo de nome , então essa consulta funcionará.

Situação dois.

Retorne uma lista de funcionários com tarefas atrasadas. Veja como essa consulta ficaria em SQL:

SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();

DISTINCTé usado porque pode haver muitas tarefas atribuídas a um usuário.

E agora vamos escrever a mesma consulta em HQL:

select distinct employee from EmployeeTask where deadline < CURDATE();

funcionário nesta consulta é um campo da classe EmployeeTask

Situação três.

Atribua todas as tarefas não atribuídas ao diretor. A consulta SQL ficará assim:

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

E agora vamos escrever a mesma consulta em HQL:

update EmployeeTask set employee = :user where employee is null

A última consulta é a mais difícil. Precisamos passar o ID, diretor, mas a classe EmployeeTask não contém um campo onde você pode escrever o id, ao contrário, contém um campo Employee onde você precisa atribuir uma referência a um objeto do tipo Employee.

No Hibernate, esse problema é resolvido com a ajuda de parâmetros de consulta que são passados ​​para o objeto Consulta. E no próprio HQL, esses parâmetros são escritos por meio de dois pontos: :user. Mas falaremos sobre isso um pouco mais tarde.