выборка из нескольких таблиц criteria hibernate

307
18 апреля 2017, 07:29

Вопрос, видимо, не сложный, но не могу понять сам принцип. У меня есть две таблицы со связью "один-ко-многим", но я не знаю как сделать выборку из них используя Criteria и поместить данные в DTO. SQL-запрос выглядит следующим образом:

SELECT DEPARTMENT.id, DEPARTMENT.name, empl.id, empl.name, empl.age
FROM EMPLOYEE AS empl
LEFT JOIN DEPARTMENT ON DEPARTMENT.id = empl.deapartment_id
WHERE empl.age = '15';

вот мои ентити:

@Entity
@Table(name = "DEPARTMENT")
public class Department implements Serializable {
@Id
@Column(name = "id", unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "name", unique = false, updatable = true, length = 45)
private String name;
@OneToMany(mappedBy = "departmentId", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<Employee> employeesSet;
public Department() {
}
public Department(String name) {
    this.name = name;
}
public Department(int id, String name) {
    this.id = id;
    this.name = name;
}
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public Set<Employee> getEmployeesSet() {
    return employeesSet;
}
public void setEmployeesSet(Set<Employee> employeesSet) {
    this.employeesSet = employeesSet;
}
@Override
public String toString() {
    return "Department{" +
            "id=" + id +
            ", name=" + name + "}\n";
}
}

@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "deapartment_id", updatable = true)
private int departmentId;
@Column(name = "age")
private String age;
@Column(name = "name", length = 25)
private String name;
public Employee() {
}
public Employee(String name,  String age, int departmentId) {
    this.setName(name);
    this.setAge(age);
    this.setDepartmentId(departmentId);
}
public Employee(int id, String name,  String age, int departmentId) {
    this.setId(id);
    this.setName(name);
    this.setAge(age);
    this.setDepartmentId(departmentId);
}
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getAge() {
    return age;
}
public void setAge(String age) {
    this.age = age;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public int getDepartmentId() {
    return departmentId;
}
public void setDepartmentId(int departmentId) {
    this.departmentId = departmentId;
}

@Override
public String toString() {
    return "Employee{" +
            " id=" + id +
            ", name=" + name +
            ", age=" + age +
            ", departmentId=" + departmentId +
" }\n";
 }
}

А вот мой DTO:

public class SomeDto2 {
private int departmentId;
private String depName;
private String age;
private String emplName;

public SomeDto2() {
}
public SomeDto2(int departmentId, String age, String emplName, String depName) {
    this.departmentId = departmentId;
    this.age = age;
    this.emplName = emplName;
    this.depName = depName;
}
public int getDepartmentId() {
    return departmentId;
}
public void setDepartmentId(int departmentId) {
    this.departmentId = departmentId;
}
public String getAge() {
    return age;
}
public void setAge(String age) {
    this.age = age;
}
public String getDepName() {
    return depName;
}
public void setDepName(String depName) {
    this.depName = depName;
}
public String getEmplName() {
    return emplName;
}
public void setEmplName(String emplName) {
    this.emplName = emplName;
}
@Override
public String toString() {
    return "SomeDto2{" +
            "departmentId=" + departmentId +
            ", age='" + age + '\'' +
            ", emplName='" + emplName + '\'' +
            ", depName='" + depName + '\'' +
            '}';
}
}

Пробовал сделать так:

List<SomeDto2> employees  = session.createCriteria(Department.class, "dep")
    .createAlias("dep.employeesSet", "empl")
    .add(Restrictions.eq("empl.age", "15"))
    .setResultTransformer(
            new AliasToBeanResultTransformer(SomeDto2.class)).list();

При этом получаю:

 java.lang.ClassCastException: ru.javastudy.hibernate.model.services.db.dto.SomeDto2 cannot be cast to java.util.Map 

Если кто-то знает хороший ресурс по хиберу с примерами кода (особенно по Сriteria), поделитесь пожалуйста, потому что с документации мне много чего пока не ясно.

Answer 1

Во-первых, судя по типу в левой части присвоения и имени переменной, вам нужны именно сотрудники, но выбирать вы начинаете с отделов. Это странно. Во-вторых, почему бы не сделать отношение двусторонним, заменив departmentId в сущности Employee на @ManyToOne department? В-третьих, вам не нужен left join чтобы получить 15-летних сотрудников. В-четвёртых, AliasToBeanResultTransformer() - это угрюмое эхо далёкого прошлого, в 4-м и 5-м Hibernate применяется Transformers.aliasToBean(). Наконец, вы уверены, что DTO вам нужен? Цитата из "Hibernate ORM User Guide", глава 26 "Best Practices":

Hibernate frees the developer from writing tedious Data Transfer Objects (DTO). In a traditional EJB architecture, DTOs serve dual purposes: first, they work around the problem that entity beans are not serializable; second, they implicitly define an assembly phase where all data to be used by the view is fetched and marshalled into the DTOs before returning control to the presentation tier. Hibernate eliminates the first purpose. Unless you are prepared to hold the persistence context (the session) open across the view rendering process, you will still need an assembly phase. Think of your business methods as having a strict contract with the presentation tier about what data is available in the detached objects.

READ ALSO
Присвоить onClickListener кнопкам, созданным в цикле

Присвоить onClickListener кнопкам, созданным в цикле

Необходимо присвоить кнопке, созданной программно в цикле, отдельный onClickListenerЯ написал свой код, но он каждой кнопке присваивает Listener последней...

181
Передать в action данные из адресной строки

Передать в action данные из адресной строки

Допустим, мы находимся на странице (неважно какой) и у нас в адресной строке что-то вроде: https://sitecom/app/backend

173
Блоки в ряд, адаптация по ширене экрана

Блоки в ряд, адаптация по ширене экрана

Помогите расположить три блока в строку на всю ширину экрана, так, чтобы левый и правый имели фиксированную ширину, а средний адаптивно сжимался...

237