Many-to-many relationship là gì

Định nghĩa One-to-Many Relationship là gì?

One-to-Many RelationshipOne-to-Nhiều mối quan hệ. Đây là nghĩa tiếng Việt của thuật ngữ One-to-Many Relationship – một thuật ngữ thuộc nhóm Technology Terms – Công nghệ thông tin.

Độ phổ biến(Factor rating): 5/10

Trong cơ sở dữ liệu quan hệ, mối quan hệ một-nhiều xảy ra khi một kỷ lục cha mẹ trong một bảng có khả năng có thể tham khảo một số hồ sơ trẻ em trong bảng khác. Trong một mối quan hệ một-nhiều, phụ huynh không cần phải có hồ sơ trẻ em; Vì vậy, các mối quan hệ một-nhiều phép zero con hồ sơ, một kỷ lục con một hay nhiều hồ sơ trẻ em. Điều quan trọng là đứa trẻ không thể có nhiều hơn một hồ sơ cha mẹ.

Xem thêm: Thuật ngữ công nghệ A-Z

Giải thích ý nghĩa

Hãy xem xét một cơ sở dữ liệu để ghi thông tin bán hàng tại một cửa hàng. Có hai bảng trong cơ sở dữ liệu này:

What is the One-to-Many Relationship? – Definition

In relational databases, a one-to-many relationship occurs when a parent record in one table can potentially reference several child records in another table. In a one-to-many relationship, the parent is not required to have child records; therefore, the one-to-many relationship allows zero child records, a single child record or multiple child records. The important thing is that the child cannot have more than one parent record.

Understanding the One-to-Many Relationship

Consider a database for recording sales information in a store. There are two tables in this database:

Thuật ngữ liên quan

  • Database (DB)
  • Record
  • Table
  • Many-to-Many Relationship
  • Entity-Relationship Diagram (ERD)
  • Enterprise Relationship Management (ERM)
  • Entity
  • Attribute
  • Primary Key
  • Foreign Key

Source: One-to-Many Relationship là gì? Technology Dictionary – Filegi – Techtopedia – Techterm

Many To many Relationship là mối quan hệ hơi phức tạp hơn mối quan hệ 1 - 1 và 1- n. Ví dụ một user có thể có nhiều role khác nhau, trong đó role cũng được liên kết với nhiều user khác nhau.

Vì vậy, trong hướng dẫn này, tôi sẽ hướng dẫn bạn tạo migrate, tạo dữ liệu và truy xuất dữ liệu trong Many to many Relationship.

Trong ví dụ này, tôi sẽ tạo các bảng "users", "roles" và "role_users", mỗi bảng đều được liên kết với nhau. Bây giờ chúng ta sẽ tạo Many to many Relationship bằng cách sử dụng laravel Eloquent Model. Đầu tiên chúng ta sẽ tạo migrate, model,  truy vấn dữ liệu và sau đó là cách tạo dữ liệu. Vì vậy, chúng ta sẽ thử một làm một ví dụ với cấu trúc bảng cơ sở dữ liệu như sau

Many-to-many relationship là gì

Many to Many Relationship sẽ sử dụng  "belongsToMany()" cho mối quan hệ.

Bây giờ chúng ta phải tạo bảng users, bảng roles, bảng role_users và thêm foreign key với bảng users và bảng roles. Vì vậy, bạn hãy tạo như hướng dẫn dưới đây:

Tạo migrations

Migration bảng users

Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); });

Migration bảng roles

Schema::create('roles', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps(); });

Migration bảng role_users

Schema::create('role_users', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('user_id'); $table->unsignedBigInteger('role_id'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); $table->timestamps(); });

Tạo models

Model bảng users

belongsToMany(Role::class, 'role_user'); } }

Model bảng roles

belongsToMany(User::class, 'role_user'); } }

Model bảng role_users

Truy vấn dữ liệu $user = User::find(1); dd($user->roles); $role = Role::find(1); dd($role->users);

Tạo mới dữ liệu

$user = User::find(2); $roleIds = [1, 2]; $user->roles()->attach($roleIds); $user = User::find(3); $roleIds = [1, 2]; $user->roles()->sync($roleIds); $role = Role::find(1); $userIds = [3, 4]; $role->users()->attach($userIds); $role = Role::find(2); $userIds = [3, 4]; $role->users()->sync($userIds);

Tôi hy vọng bạn thích hướng dẫn này. Nếu bạn có bất kỳ câu hỏi nào hãy liên hệ với chúng tôi qua trang contact. Cảm ơn bạn.

Code ví dụ Hibernate @ManyToMany – Quan hệ nhiều nhiều.

(Xem thêm: Hướng dẫn tự học Hibernate)

Trong thiết kế database,  khi xuất hiện quan hệ nhiều nhiều (n-n) thì ta sẽ tạo một bảng trung gian để chuyển quan hệ nhiều nhiều đó thành 2 quan hệ một nhiều.

Ví dụ:

Ví dụ mình có 1 bảng product (sản phẩm) và 1 bảng category (danh mục). Quan hệ giữa hai bảng này là nhiều – nhiều vì 1 sản phẩm có thể thuộc nhiều danh mục khác nhau, một danh mục cũng có thể chứa nhiều sản phẩn khác nhau.

Khi thiết kế database ta sẽ tạo 1 bảng chung gian để biến đổi nó thành 2 quan hệ một nhiều:

Ở đây mình tạo bảng trung gian là product_category, từ quan hệ nhiều nhiều giữa product với category nó sẽ thành 2 quan hệ một nhiều là product với product_category và category với product_category

Tạo database

CREATE SCHEMA `hibernate-demo-4` ; CREATE TABLE `hibernate-demo-4`.`product` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NULL, PRIMARY KEY (`id`)); CREATE TABLE `hibernate-demo-4`.`category` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NULL, PRIMARY KEY (`id`)); CREATE TABLE `hibernate-demo-4`.`product_category` ( `product_id` INT NOT NULL, `category_id` INT NOT NULL, PRIMARY KEY (`product_id`, `category_id`), CONSTRAINT `fk-category` FOREIGN KEY (`category_id`) REFERENCES `hibernate-demo-4`.`category` (`id`), CONSTRAINT `fk-product` FOREIGN KEY (`product_id`) REFERENCES `hibernate-demo-4`.`product` (`id`));

Các công nghệ sử dụng:

  • Maven
  • JDK 1.8
  • Eclipse
  • MySQL

Cấu trúc project

Các thư viện sử dụng

4.0.0 stackjava.com HibernateManyToManyDemo 0.0.1-SNAPSHOT 1.8 1.8 5.3.6.Final org.hibernate hibernate-core ${hibernate.version} org.hibernate hibernate-entitymanager ${hibernate.version} mysql mysql-connector-java 5.1.46

File cấu hình hibernate, kết nối tới MySQL

Demo Hibernate Entity Manager org.hibernate.jpa.HibernatePersistenceProvider

Trong ví dụ này mình sử dụng entityManager nên sẽ khai báo file persistence.xml nếu các bạn sử dụng hibernateSession thì có thể khai báo file hibernate.cfg.xml

(Xem lại: Code ví dụ Hibernate EntityManager, EntityManagerFactory)

(Xem lại: Code ví dụ Hibernate Session, SessionFactory)

Các class entities

package stackjava.com.hibernatedemo.entities; import java.util.HashSet; import java.util.Set; import javax.persistence.*; @Entity @Table(name = "category") public class Category { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "name") private String name; @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name = "product_category", joinColumns = { @JoinColumn(name = "category_id") }, inverseJoinColumns = {@JoinColumn(name = "product_id") }) private Set products = new HashSet<>(); @Override public String toString() { return "Category [id=" + id + ", name=" + name + " - products size: " + products.size() + "]"; } // setter - getter }
  • Để biểu thị mối quan hệ nhiều nhiều ta dùng annotation @ManyToMany
  • Annotation @JoinTable sẽ chỉ rõ bảng trung gian trong thuộc tính name, thuộc tính joinColumns sẽ chỉ rõ column mapping với tale hiện tại, thuộc tính inverseJoinColumns sẽ chỉ rõ column mapping với table còn lại
package stackjava.com.hibernatedemo.entities; import java.util.Set; import javax.persistence.*; @Entity @Table(name = "product") public class Product { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "name") private String name; @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name = "product_category", joinColumns = { @JoinColumn(name = "product_id") }, inverseJoinColumns = {@JoinColumn(name = "category_id") }) private Set categories = new HashSet<>(); @Override public String toString() { return "Product [id=" + id + ", name=" + name + " - categories size: " + categories.size() +"]"; } // getter - setter }

Demo 1

Insert 1 category với nhiều product

package stackjava.com.hibernatedemo; import java.util.HashSet; import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import stackjava.com.hibernatedemo.entities.Category; import stackjava.com.hibernatedemo.entities.Product; public class DemoInsert1 { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); Category category = new Category("Electronic Device"); Product product1 = new Product("Television"); Product product2 = new Product("Iphone"); Product product3 = new Product("Samsung Galaxy S9"); Set products = new HashSet<>(); products.add(product1); products.add(product2); products.add(product3); entityManager.persist(category); entityManager.getTransaction().commit(); System.out.println("-------------------------------"); System.out.println(category); System.out.println(product1); System.out.println(product2); System.out.println(product3); entityManager.close(); entityManagerFactory.close(); } }

Kết quả:

Hibernate: insert into category (name) values (?) Hibernate: insert into product (name) values (?) Hibernate: insert into product (name) values (?) Hibernate: insert into product (name) values (?) ------------------------------- Category [id=1, name=Electronic Device - products size: 3] Product [id=2, name=Television - categories size: 0] Product [id=3, name=Iphone - categories size: 0] Product [id=1, name=Samsung Galaxy S9 - categories size: 0]

Ở đây mình đang để cascade = CascadeType.ALL nên khi persist category, các product của category cũng được persist theo

(Xem lại: Code ví dụ Hibernate cascade, annotation @Cascade.)

Demo 2

Persist 1 product với nhiều category.

Bây giờ mình thực hiện lấy product có id = 2 vừa tạo ở trên, thêm mới category cho nó và thực hiện lưu lại.

package stackjava.com.hibernatedemo; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import stackjava.com.hibernatedemo.entities.Category; import stackjava.com.hibernatedemo.entities.Product; public class DemoInsert2 { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); Category category = new Category("Home Applicances"); Product product = entityManager.find(Product.class, 2); product.getCategories().add(category); entityManager.getTransaction().commit(); System.out.println("--------- after insert -------------"); System.out.println(category); System.out.println(product); entityManager.close(); entityManagerFactory.close(); } }

Kết quả:

Hibernate: select product0_.id as id1_1_0_, product0_.name as name2_1_0_ from product product0_ where product0_.id=? Hibernate: select categories0_.product_id as product_1_2_0_, categories0_.category_id as category2_2_0_, category1_.id as id1_0_1_, category1_.name as name2_0_1_ from product_category categories0_ inner join category category1_ on categories0_.category_id=category1_.id where categories0_.product_id=? Hibernate: insert into category (name) values (?) Hibernate: insert into product_category (product_id, category_id) values (?, ?) --------- after insert ------------- Category [id=2, name=Home Applicances - products size: 0] Product [id=2, name=Television - categories size: 2]

Check lại database:

Bảng category

Bảng product

Bảng product_category

Demo 3

Thực hiện lấy dữ liệu của category có id = 1, và product có id = 2 và in ra dữ liệu của chúng:

package stackjava.com.hibernatedemo; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import stackjava.com.hibernatedemo.entities.Category; import stackjava.com.hibernatedemo.entities.Product; public class DemoSelect { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); Category category = entityManager.find(Category.class, 1); System.out.println(category); category.getProducts().forEach(p -> System.out.println(p)); System.out.println("-------------------------------"); Product product = entityManager.find(Product.class, 2); System.out.println(product); product.getCategories().forEach(c -> System.out.println(c)); entityManager.close(); entityManagerFactory.close(); } }

Kết quả:

Category [id=1, name=Electronic Device - products size: 3] Product [id=3, name=Iphone - categories size: 1] Product [id=1, name=Samsung Galaxy S9 - categories size: 1] Product [id=2, name=Television - categories size: 2] ------------------------------- Product [id=2, name=Television - categories size: 2] Category [id=1, name=Electronic Device - products size: 3] Category [id=2, name=Home Applicances - products size: 1]

Okay, Done!

Download code ví dụ trên tại đây.

References:

https://docs.jboss.org/…/ManyToMany.html