หลังจากที่ผ่านมาได้พูดถึงการจัดการ GORM Relationship แบบ One-to-Many กันแล้วมา entry นี้จะมาพูดถึงการจัดการความสัมพันธ์แบบ many-to-many กันบ้าง
เริ่มกันเลย ……..
ในการจัดการความสัมพันธ์แบบนี้ โดยทั่วไปนั้นจะสร้าง table กลางขึ้นมาเพื่อเชื่อมความสัมพันธ์กันดังรูป

ซึ่งจะมองได้ว่าเป็นมีความสัมพันธ์ขึ้นดังนี้
BookWriter –> Book
BookWriter –> Writer
เมื่อมาจัดการความสัมพันธ์ลักษณะนี้ใน GORM สามารถทำได้ง่าย โดยจุดสำคัญอยู่ที่ domain class : BookWriter จะเป็นตัวเชื่อมความสัมพันธ์ของ Book และ Writer ดังนี้
Book.groovy
class Book {
String name
}
Writer.groovy
class Writer {
String name
}
BookWriter.groovy
import Writer
class BookWriter {
static belongsTo = [ book:Book, writer:Writer ]
}
คำอธิบาย
static belongsTo = [ book:Book, writer:Writer ] จะใช้กำหนดเจ้าของความสัมพันธ์นี้ ซึ่งก็คือ Book และ Writer
ลองมาสร้างข้อมูลกัน
//1. สร้าง Book def b = new Book( name:"Book Name" ) b.save() //2. สร้าง Writer def w = new Writer( name:"Writer Name" ) w.save() //3. สร้างความสัมพันธ์ของ Book และ Writer def bw = new BookWriter( book:b, writer:w ) bw.save()
ตัวอย่างการดึงข้อมูล ซึ่งจะใช้ domain class BookWriter เป็นหลักดังนี้
println BookWriter.get(1).book.name println BookWriter.get(1).writer.name
หรืออาจจะใช้ Criteria มาช่วย ดังนี้
def bw = BookWriter.createCriteria()
def results = bw.list {
book {
like("name", "Book%")
}
writer {
like("name", "Writer%")
}
}
println results
จะเห็นว่าการใช้งาน Criteria ทำให้ชีวิตง่ายขึ้นมาอีก เนื่องจากสามารถใส่เงื่อนไขต่างๆ เป็น closure ได้เลย หรือถ้าใครถนัด Hibernate มากกว่าอาจ Hibernate Query Language [ HQL ] ได้
จากตัวอย่างด้านบนนั้นใน Book และ Writer จะไม่รู้เลยว่ามีความสัมพันธ์อะไรบ้าง ยกเว้นจะไปดูใน BookWriter แต่เราสามารถกำหนดเพิ่มเพื่อให้ Book และ Writer โดยการเพิ่ม code ดังนี้ไปยังทั้ง 2 domain classes
static hasMany = [bookWriters: BookWriter] // สามารถทำ cascade delete ได้
วิธีการดังกล่าวนั้นเป็นวิธีการที่ make sense ในโลกของ RDBMS แต่ในโลกของ Object Oriented มันรู้สึกแปลกๆ คุณว่าไหม ??? มันน่าจะมีวิธีการที่เหมาะสมกับโลกของ Object Oriented สิ
ดังนั้น GORM จึงขอเสนออีกหนึ่งวิธีดังนี้
โดยการใช้ hasMany ในการกำหนดความสัมพันธ์แบบ one-to-many ทั้งสองฝั่ง
ดังนั้นสามารถกำหนดใน GORM ได้ดังนี้
Book.groovy
class Book{
static hasMany = [ writers : Writer ] // ชนิดของ writers คือ java.util.Set
String name
}
Writer.groovy
class Writer {
// กำหนดให้ Book เป็นเจ้าของความสัมพันธ์ [ Unidirection ] เพื่อป้องกันการ cascade delete
static belongsTo = Book
static hasMany = [ books: Book ] // ชนิดของ books คือ java.util.Set
String name
}
ตัวอย่างการสร้าง
def book = new Book( name:"Book Name" )
book.writers = [
new Writer( name : "Writer Name 1"),
new Writer( name : "Writer Name 2")
]
book.save()
จะเห็นได้ว่าสามารถสร้างข้อมูลได้อย่างง่ายดาย แต่ในทางกลับกันไม่สามารถทำการสร้างแบบ reverse ได้ ดังตัวอย่าง
def writer = new Writer( name:"Writer Name" ); writer.books = [ new Book( name:"Book Name 1" ), new Book( name:"Book Name 2" ) ] writer.save();
ซึ่งข้อจำกัดนี้จะเหมือนกับ Hibernate ซึ่งเป็น core ของ GORM [ สามารถจัดการความสัมพันธ์แบบ many-to-many ได้เพียงด้านเดียวเท่านั้น ]
ในการลบข้อมูลในความสัมพันธ์แบบนี้จะไม่ทำงานลบข้อมูลของ Writer ด้วย เนื่องจากสามารถมีความสัมพันธ์กับ Book อื่นๆได้
def book= Book.get(1); book.delete();
นี่ก็คือการจัดการความสัมพันธ์แบบ many-to-many ใน GORM ครับ
ง่ายหรือเปล่าครับ ????
Web Reference
http://grails.org/doc/1.0.x/
2 Responses to “การจัดการ GORM Relationship แบบ Many-to-Many”
Trackbacks/Pingbacks
Leave a Reply