Banyak ke Banyak Hubungan

Many to Many relationshipantara dua tabel dicapai dengan menambahkan tabel asosiasi sehingga memiliki dua kunci asing - satu dari kunci primer setiap tabel. Selain itu, pemetaan kelas ke dua tabel memiliki atribut dengan kumpulan objek tabel asosiasi lain yang ditetapkan sebagai atribut sekunder dari fungsi relationship ().

Untuk tujuan ini, kita akan membuat database SQLite (mycollege.db) dengan dua tabel - departemen dan karyawan. Di sini, kami berasumsi bahwa seorang karyawan adalah bagian dari lebih dari satu departemen, dan sebuah departemen memiliki lebih dari satu karyawan. Ini merupakan hubungan banyak-ke-banyak.

Definisi kelas Karyawan dan Departemen yang dipetakan ke tabel departemen dan karyawan adalah sebagai berikut -

from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
engine = create_engine('sqlite:///mycollege.db', echo = True)
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy.orm import relationship

class Department(Base):
   __tablename__ = 'department'
   id = Column(Integer, primary_key = True)
   name = Column(String)
   employees = relationship('Employee', secondary = 'link')
   
class Employee(Base):
   __tablename__ = 'employee'
   id = Column(Integer, primary_key = True)
   name = Column(String)
   departments = relationship(Department,secondary='link')

Kami sekarang mendefinisikan kelas Link. Ini ditautkan ke tabel tautan dan berisi atribut department_id dan employee_id yang masing-masing merujuk ke kunci utama tabel departemen dan karyawan.

class Link(Base):
   __tablename__ = 'link'
   department_id = Column(
      Integer, 
      ForeignKey('department.id'), 
      primary_key = True)

employee_id = Column(
   Integer, 
   ForeignKey('employee.id'), 
   primary_key = True)

Di sini, perlu diperhatikan bahwa kelas Departemen memiliki atribut karyawan yang terkait dengan kelas Karyawan. Atribut sekunder fungsi hubungan diberi tautan sebagai nilainya.

Demikian pula, kelas Karyawan memiliki atribut departemen yang terkait dengan kelas Departemen. Atribut sekunder fungsi hubungan diberi tautan sebagai nilainya.

Ketiga tabel ini dibuat ketika pernyataan berikut dijalankan -

Base.metadata.create_all(engine)

Konsol Python memancarkan kueri CREATE TABLE berikut -

CREATE TABLE department (
   id INTEGER NOT NULL,
   name VARCHAR,
   PRIMARY KEY (id)
)

CREATE TABLE employee (
   id INTEGER NOT NULL,
   name VARCHAR,
   PRIMARY KEY (id)
)

CREATE TABLE link (
   department_id INTEGER NOT NULL,
   employee_id INTEGER NOT NULL,
   PRIMARY KEY (department_id, employee_id),
   FOREIGN KEY(department_id) REFERENCES department (id),
   FOREIGN KEY(employee_id) REFERENCES employee (id)
)

Kami dapat memeriksa ini dengan membuka mycollege.db menggunakan SQLiteStudio seperti yang ditunjukkan pada tangkapan layar yang diberikan di bawah ini -

Selanjutnya kita membuat tiga objek kelas Departemen dan tiga objek kelas Karyawan seperti yang ditunjukkan di bawah ini -

d1 = Department(name = "Accounts")
d2 = Department(name = "Sales")
d3 = Department(name = "Marketing")

e1 = Employee(name = "John")
e2 = Employee(name = "Tony")
e3 = Employee(name = "Graham")

Setiap tabel memiliki atribut koleksi yang memiliki metode append (). Kita dapat menambahkan objek Karyawan ke koleksi Karyawan di objek Departemen. Demikian pula, kita dapat menambahkan objek Departemen ke atribut koleksi departemen dari objek Karyawan.

e1.departments.append(d1)
e2.departments.append(d3)
d1.employees.append(e3)
d2.employees.append(e2)
d3.employees.append(e1)
e3.departments.append(d2)

Yang harus kita lakukan sekarang adalah menyiapkan objek sesi, menambahkan semua objek ke dalamnya dan melakukan perubahan seperti yang ditunjukkan di bawah ini -

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
session.add(e1)
session.add(e2)
session.add(d1)
session.add(d2)
session.add(d3)
session.add(e3)
session.commit()

Pernyataan SQL berikut akan dipancarkan di konsol Python -

INSERT INTO department (name) VALUES (?) ('Accounts',)
INSERT INTO department (name) VALUES (?) ('Sales',)
INSERT INTO department (name) VALUES (?) ('Marketing',)
INSERT INTO employee (name) VALUES (?) ('John',)
INSERT INTO employee (name) VALUES (?) ('Graham',)
INSERT INTO employee (name) VALUES (?) ('Tony',)
INSERT INTO link (department_id, employee_id) VALUES (?, ?) ((1, 2), (3, 1), (2, 3))
INSERT INTO link (department_id, employee_id) VALUES (?, ?) ((1, 1), (2, 2), (3, 3))

Untuk memeriksa pengaruh operasi di atas, gunakan SQLiteStudio dan lihat data di tabel departemen, karyawan, dan tautan -

Untuk menampilkan data, jalankan pernyataan query berikut -

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()

for x in session.query( Department, Employee).filter(Link.department_id == Department.id, 
   Link.employee_id == Employee.id).order_by(Link.department_id).all():
   print ("Department: {} Name: {}".format(x.Department.name, x.Employee.name))

Sesuai data yang diisi dalam contoh kami, output akan ditampilkan seperti di bawah ini -

Department: Accounts Name: John
Department: Accounts Name: Graham
Department: Sales Name: Graham
Department: Sales Name: Tony
Department: Marketing Name: John
Department: Marketing Name: Tony