@ManyToOne

All lectures for KY purposes
Деңгээл , Сабак
жеткиликтүү

2.1 Таблицалар деңгээлинде байланыштыруу

Hibernate'тин коллекцияларды коштоочу таблицаларда кантип сактай тургандыгы менен тааныштык. Эми толук кандуу таблицаларда, чыныгы Entity-класстарды сактаган таблицаларда байланышты кантип уюштурууну карап чыгабыз.

Entity-класстар ортосунда Hibernate'те төрт түрдүү мамиле бар:

  • one-to-one
  • one-to-many
  • many-to-one
  • many-to-many

Биз эң жөнөкөй вариантыңан баштайбыз – many-to-one.

SQL таблицалары ортосундагы мындай мамилеге сен буга чейин кезигип калдың. Бул адатта мындай көрүнөт:

id name occupation salary age join_date
1 Иванов Иван Программист 100000 25 2012-06-30
2 Петров Петр Программист 80000 23 2013-08-12
3 Иванов Сергей Тестировщик 40000 30 2014-01-01
4 Рабинович Мойша Директор 200000 35 2015-05-12
5 Кириенко Анастасия Офис-менеджер 40000 25 2015-10-10
6 Васька Кот 1000 3 2018-11-11

employee таблицасы:

Бул таблицада мындай колонкалар бар:

  • id INT
  • name VARCHAR
  • occupation VARCHAR
  • salary INT
  • age INT
  • join_date DATE

Ал эми мындай көрүнөт task таблицасы, ал кызматкерлерге арналган тапшырмаларды камтыйт:

id employee_id name deadline
1 1 Фронтендтеги баганы оңдоо 2022-06-01
2 2 Бэкендтеги баганы оңдоо 2022-06-15
3 5 Кофе сатып алуу 2022-07-01
4 5 Кофе сатып алуу 2022-08-01
5 5 Кофе сатып алуу 2022-09-01
6 (NULL) Офисти тазалоо (NULL)
7 4 Жашоодон ырахат алуу (NULL)
8 6 Жашоодон ырахат алуу (NULL)

Бул таблицада болгону 4 колонка бар:

  • id – тапшырманын уникалдуу номери (жана таблицадагы катар);
  • employee_id – employee таблицасындагы кызматкердин ID, тапшырма ага таандык;
  • name – тапшырманын аталышы жана сүрөттөлүшү;
  • deadline – тапшырманы аткаруу үчүн берилген убакыт.

Биз көрүп турабыз, task таблицасындагы көптөгөн катарлар employee таблицасындагы бир жазууга шилтеме жасай алышат. Таблицалар деңгээлинде мындай байланыш көптөн-бирге (many-to-one) деп аталат.

2.2 Java-класстар деңгээлинде байланыштыруу

Таблицалар деңгээлинде байланыштыруу менен кошо, Hibernate'те Entity-класстар деңгээлинде дагы байланыштырып уюштурууга болот. Бул @ManyToOne аннотациясы аркылуу жасалат.

Бирок башында жөн гана эки класс түзүп алабыз: Employee жана EmployeeTask:


@Entity @Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String name;
 
   @Column(name="occupation")
   public String occupation;
 
   @Column(name="salary")
   public Integer salary;
 
   @Column(name="join_date")
   public Date join;
}

Ал эми кызматкерлердин тапшырмаларын сактоо үчүн экинчи класс:


@Entity @Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String description;
 
  @Column(name="employee_id")
   public Integer employeeId;
 
   @Column(name="deadline")
   public Date deadline;
}

Бул класстар менен баары жакшы, бирок алар ортосунда эч кандай байланыш жок, ал кээ бир талаалар бири-бирине шилтеме жасаган фактты чагылдырса болмок. Эми аны оңдоп алабыз.

2.3 @ManyToOne аннотациясы.

Биринчи кезекте, Java'да биз объекттер (жана объекттерге шилтемелер) менен иштешүүгө көнүп калганбыз, алардын id'лери менен эмес. Андыктан, эң биринчи ишибиз EmployeeTask классындагы employeeId талаасынын ордуна, Employee типтеги объектке шилтемени көрсөтөбүз. Биздин жаңы класс ушундай көрүнөт:


@Entity @Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String description;
 
   @ManyToOne @JoinColumn(name = "employee_id")
   public Employee employee;
 
   @Column(name="deadline")
   public Date deadline;
}

Аннотациясын @ManyToOne колдонуп, биз көптөгөн EmployeeTask объекттери бир Employee типтеги объектке шилтеме жасай ала турганын көрсөттүк. Ошондой эле аннотациясынын @JoinColumn жардамы менен Employee объекттеринин id'и таблицанын кайсыл колонкасында сакталарын белгиледик.

2.4 Сурамжылоолор мисалдары

Эми бир нече мисал көрсөтүп берейин, Hibernate мындай байланыштырылган класстар менен кандайча иштей аларын.

Биринчи сценарий

Белгилүү бир колдонуучуга тапшырылган бардык тапшырмаларды билиш үчүн сурам жазалы. Бул кантип HQL'де көрүнөрүн карагыла:

from EmployeeTask where employee.name = "Иван Иванович"

Сен жөн гана такталары класстардын талаалары аркылуу чакырып өтүп кетсең болот. Бул абдан ыңгайлуу. Бирок да сурамды Java-код түрүндө жазып көрөлү:


String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Иван Иванович");
List<EmployeeTask> resultLIst = query.list();

Экинчи сценарий

Просроченные тапшырмалары бар кызматкерлердин тизмесин кайтарган сурам жазалы. Эгерде тапшырманын deadline убактысы өткөн болсо, анда ал тапшырма просроченный. Бул сурам SQL'де кантип көрүнөөрүн карагыла:


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

DISTINCT колдонулат, анткени бир колдонуучуга көп тапшырма берилген болушу мүмкүн.

Эми бул сурамды HQL'де жазалы:

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

Employee сурамында – бул EmployeeTask классынын талаасы

Үчүнчү ситуация

Бардык дайындалбаган тапшырмаларды директорго дайындап койолу. SQL боюнча сурам мындай көрүнөт:


UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

Эми бул сурамды HQL'де жазалы:

update EmployeeTask set employee = :user where employee is null

Акыркы сурам татаалыраак. Бизге директордун ID'ин берүү керек, бирок EmployeeTask классы id жазуу үчүн талаа камтыбайт, анын ордуна Employee объектине шилтеме жасай турган талаа камтыйт.


Employee director = session.get(Employee.class, 4);
 
String hql = "update EmployeeTask set employee = :user where employee is null";
Query<EmployeeTask> query = session.createQuery(hql, EmployeeTask.class);
query.setParameter("user", director);
query.executeUpdate();

Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION