@ManyToMany

All lectures for BN purposes
লেভেল 1 , পাঠ 846
বিদ্যমান

পরিষেবা টেবিল

এখন আরেকটা সাধারণ কেস দেখি - অনেক-থেকে-অনেক। আসুন কল্পনা করি যে আমাদের কাজ এবং কর্মচারীদের মধ্যে বহু-থেকে-অনেক সম্পর্ক রয়েছে :

  • কর্মচারী টেবিলে একজন কর্মচারী টাস্ক টেবিল থেকে অনেকগুলি কাজ করতে পারে।
  • টাস্ক টেবিলে একটি কাজ বেশ কয়েকটি কর্মচারীকে বরাদ্দ করা যেতে পারে।

সত্তার মধ্যে এই সম্পর্ককে বলা হয় বহু-থেকে-বহু। এবং SQL স্তরে এটি বাস্তবায়ন করার জন্য, আমাদের একটি অতিরিক্ত পরিষেবা টেবিল প্রয়োজন। আসুন এটিকে কল করি, উদাহরণস্বরূপ, কর্মচারী_টাস্ক।

কর্মচারী_টাস্ক টেবিলে শুধুমাত্র দুটি কলাম থাকবে:

  • কর্মচারী আইডি
  • task_id

প্রতিবার যখন আমরা একটি নির্দিষ্ট ব্যবহারকারীকে একটি নির্দিষ্ট কাজ বরাদ্দ করি, এই টেবিলে একটি নতুন সারি যোগ করা হবে। উদাহরণ:

কর্মচারী আইডি task_id
1 1
1 2
2 3

ঠিক আছে, টাস্ক টেবিলের কর্মীর_আইডি কলামটি হারাতে হবে । কাজটি শুধুমাত্র একজন কর্মচারীকে অর্পণ করা গেলেই এটি বোঝা যায়। যদি টাস্কটি বেশ কয়েকটি কর্মচারীকে অর্পণ করা যায় তবে এই তথ্যটি অবশ্যই কর্মচারী_টাস্ক পরিষেবা টেবিলে সংরক্ষণ করতে হবে ।

টেবিল-স্তরের সম্পর্ক

আমাদের নতুন টেবিলগুলি দেখতে কেমন হবে তা এখানে:

আইডি নাম পেশা বেতন বয়স তারিখ যোগ দিতে
1 ইভানভ ইভান প্রোগ্রামার 100000 25 2012-06-30
2 পেট্রোভ পেট্র প্রোগ্রামার 80000 23 2013-08-12
3 ইভানভ সের্গেই পরীক্ষক 40000 ত্রিশ 2014-01-01
4 রাবিনোভিচ মইশা পরিচালক 200000 35 2015-05-12
5 কিরিয়েনকো আনাস্তাসিয়া অফিস ব্যবস্থাপক 40000 25 2015-10-10
6 ভাস্কা বিড়াল 1000 3 2018-11-11

কর্মচারী টেবিল ( পরিবর্তিত হয়নি ) :

এই টেবিলে নিম্নলিখিত কলাম আছে:

  • আইডি আইএনটি
  • নাম VARCHAR
  • পেশা VARCHAR
  • বেতন INT
  • বয়স INT
  • join_date DATE

এবং এইভাবে টাস্ক টেবিলের মত দেখায় , কর্মচারী_আইডি কলামটি হারিয়েছে (লাল রঙে চিহ্নিত):

আইডি emploee_id নাম শেষ তারিখ
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 (খালি) অফিস পরিষ্কার করুন (খালি)
7 4 জীবন উপভোগ করুন (খালি)
8 6 জীবন উপভোগ করুন (খালি)

এই টেবিলে এখন মাত্র 3টি কলাম রয়েছে:

  • আইডি - অনন্য টাস্ক নম্বর (এবং টেবিলের সারি)
  • কর্মচারী_আইডি - (সরানো হয়েছে)
  • নাম - টাস্কের নাম এবং বিবরণ
  • সময়সীমা - যে সময় পর্যন্ত কাজটি শেষ করতে হবে

আমাদের কাছে কর্মীর_টাস্ক পরিষেবা টেবিলও রয়েছে , যেখানে কর্ম টেবিল থেকে কর্মীর_আইডি ডেটা স্থানান্তরিত হয়েছে:

কর্মচারী আইডি task_id
1 1
2 2
5 3
5 4
5 5
(খালি) 6
4 7
6 8

আমি উদ্দেশ্যমূলকভাবে টাস্ক টেবিলে মুছে ফেলা কলামটি অস্থায়ীভাবে সংরক্ষণ করেছি যাতে আপনি দেখতে পারেন যে এটি থেকে ডেটা কর্মীর_টাস্ক টেবিলে চলে গেছে।

আরেকটি গুরুত্বপূর্ণ পয়েন্ট হল কর্মচারী_টাস্ক টেবিলে লাল লাইন "(NULL) 6" । আমি এটিকে লাল রঙে চিহ্নিত করেছি কারণ এটিকর্মী_টাস্ক টেবিলে থাকবে না ।

যদি টাস্ক 7 ব্যবহারকারী 4-কে বরাদ্দ করা হয়, তাহলে কর্মচারী_টাস্ক টেবিলে একটি সারি (4, 7) থাকা উচিত।

যদি টাস্ক 6 কাউকে বরাদ্দ না করা হয়, তাহলে কর্মচারী_টাস্ক টেবিলে এর জন্য কোন রেকর্ড থাকবে না। এই টেবিলের চূড়ান্ত সংস্করণগুলি দেখতে কেমন হবে তা এখানে:

টাস্ক টেবিল :

আইডি নাম শেষ তারিখ
1 ফ্রন্টএন্ডে একটি বাগ ঠিক করুন 2022-06-01
2 ব্যাকএন্ডে একটি বাগ ঠিক করুন 2022-06-15
3 কফি কিনুন 2022-07-01
4 কফি কিনুন 2022-08-01
5 কফি কিনুন 2022-09-01
6 অফিস পরিষ্কার করুন (খালি)
7 জীবন উপভোগ করুন (খালি)
8 জীবন উপভোগ করুন (খালি)

কর্মচারী_টাস্ক টেবিল:

কর্মচারী আইডি task_id
1 1
2 2
5 3
5 4
5 5
4 7
6 8

জাভা ক্লাস লেভেলে যোগাযোগ

কিন্তু সত্তা-শ্রেণীর স্তরে যোগাযোগের সাথে, আমাদের একটি সম্পূর্ণ আদেশ আছে। সুসংবাদ দিয়ে শুরু করা যাক।

প্রথমত, হাইবারনেটের একটি বিশেষ @ManyToMany টীকা রয়েছে যা আপনাকে বহু-থেকে-অনেক-টেবিল সম্পর্কের ক্ষেত্রে ভালভাবে বর্ণনা করতে দেয়।

দ্বিতীয়ত, দুটি সত্তা ক্লাস এখনও আমাদের জন্য যথেষ্ট। পরিষেবা টেবিলের জন্য আমাদের ক্লাসের প্রয়োজন নেই।

আমাদের ক্লাস দেখতে কেমন হবে তা এখানে। কর্মচারী শ্রেণী তার আসল আকারে:

@Entity
@Table(name="user")
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;
}

এবং EmployeeTask ক্লাস তার আসল আকারে:

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

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

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

@ManyToMany টীকা

আমি উদাহরণগুলিতে বিদ্যমান ক্ষেত্রগুলি বাদ দেব, তবে আমি নতুনগুলি যুক্ত করব। তারা দেখতে কেমন হবে তা এখানে। কর্মচারী শ্রেণী :

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

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
	       joinColumns=  @JoinColumn(name="employee_id", referencedColumnName="id"),
           inverseJoinColumns= @JoinColumn(name="task_id", referencedColumnName="id") )
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();

}

এবং EmployeeTask ক্লাস :

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

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
       	joinColumns=  @JoinColumn(name="task_id", referencedColumnName="id"),
       	inverseJoinColumns= @JoinColumn(name=" employee_id", referencedColumnName="id") )
   private Set<Employee> employees = new HashSet<Employee>();

}

মনে হচ্ছে সবকিছুই জটিল, কিন্তু আসলে সবকিছুই সহজ।

প্রথমত, এটি @JoinTable টীকা ব্যবহার করে (@JoinColumn এর সাথে বিভ্রান্ত না হওয়া), যা কর্মচারী_টাস্ক পরিষেবা টেবিল বর্ণনা করে।

দ্বিতীয়ত, এটি বর্ণনা করে যে কর্মচারী_টাস্ক টেবিলের টাস্ক_আইডি কলাম টাস্ক টেবিলের আইডি কলামকে বোঝায়।

তৃতীয়ত, এটি বলে যে কর্মচারী_টাস্ক টেবিলের কর্মচারী_আইডি কলামটি কর্মচারী টেবিলের আইডি কলামকে বোঝায়।

প্রকৃতপক্ষে, টীকাগুলির সাহায্যে, আমরা বর্ণনা করেছি যে কর্মচারী_টাস্ক টেবিলে কী ডেটা রয়েছে এবং কীভাবে হাইবারনেটের এটি ব্যাখ্যা করা উচিত।

কিন্তু এখন আমরা খুব সহজেই যেকোন কর্মীর কাছে একটি টাস্ক যোগ করতে পারি (এবং মুছে ফেলতে পারি)। এবং যে কোনও কাজের সাথে যে কোনও পারফর্মার যুক্ত করুন।

উদাহরণ অনুরোধ করুন

এই ManyToMany ক্ষেত্রগুলি কীভাবে কাজ করে তা আরও ভালভাবে বোঝার জন্য আসুন কয়েকটি আকর্ষণীয় প্রশ্ন লিখি। এবং তারা প্রত্যাশা অনুযায়ী ঠিক কাজ করে।

প্রথমত, আমাদের পুরানো কোড পরিবর্তন ছাড়াই কাজ করবে, যেহেতু পরিচালকের আগে একটি টাস্ক ফিল্ড ছিল:

EmployeeTask task1 = new EmployeeTask();
task1.description = "Do Something Important";
session.persist(task1);

EmployeeTask task2 = new EmployeeTask();
task2.description = "Nothing to do";
session.persist(task2);
session.flush();

Employee director = session.find(Employee.class, 4);
director.tasks.add(task1);
director.tasks.add(task2);

session.update(director);
session.flush();

দ্বিতীয়ত, আমরা যদি অন্য একজন পারফর্মারকে কিছু কাজের জন্য বরাদ্দ করতে চাই, তাহলে এটি করা আরও সহজ:

Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employees.add(director);

session.update(task);
session.flush();

গুরুত্বপূর্ণ ! এই অনুরোধটি কার্যকর করার ফলে, শুধুমাত্র টাস্কটিতে একজন নির্বাহক-পরিচালক থাকবে না, তবে পরিচালকেরও 101 নম্বর টাস্ক থাকবে।

প্রথমত, কর্মচারী_টাস্ক টেবিলে পরিচালক এবং টাস্কের মধ্যে সম্পর্ক সম্পর্কে তথ্য একটি স্ট্রিং হিসাবে সংরক্ষণ করা হবে: (4,101)।

দ্বিতীয়ত, @ManyToMany টীকা দিয়ে চিহ্নিত ক্ষেত্রগুলি হল প্রক্সি অবজেক্ট, এবং যখন সেগুলি অ্যাক্সেস করা হয়, একটি ডাটাবেস ক্যোয়ারী সর্বদা কার্যকর করা হয়।

সুতরাং আপনি যদি কোনও কর্মচারীর সাথে একটি টাস্ক যুক্ত করেন এবং ডাটাবেসে কর্মচারী সম্পর্কে তথ্য সংরক্ষণ করেন, তবে তার পরে কার্যটির নির্বাহকদের তালিকায় একটি নতুন নির্বাহক থাকবে।

মন্তব্য
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION