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 @ManyToOne
informa ao Hibernate que muitas entidades EmployeeTask podem se referir a uma entidade Employee .
E a anotação @JoinColumn
especifica 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.
GO TO FULL VERSION