Service layer vs DAO - ทำไมต้องทั้งคู่


64

ฉันทำงานกับ SpringMVC, Hibernate และฐานข้อมูลบางส่วนในตัวอย่างเว็บแอปพลิเคชัน java

มีสิ่งที่แตกต่างกันสองสามอย่างที่ทำเช่นนี้ แต่บทช่วยสอนการรวมฤดูใบไม้ผลิ 3 และไฮเบอร์เนตพร้อมด้วยตัวอย่างนี้มีคลาสโมเดลมุมมอง (เป็น jsp) และคลาสเซอร์วิสและ dao สำหรับคอนโทรลเลอร์

คำถามของฉันคือไม่ทั้งบริการและชั้นเรียน DAO ทำสิ่งเดียวกันหรือไม่ ทำไมคุณต้องการทั้งสองอย่าง

นี่คือการสอนที่ฉันใช้จริง: http://fruzenshtein.com/spring-mvc-security-mysql-hibernate/

คำตอบ:


60

โดยทั่วไป DAO นั้นเบาที่สุดและมีอยู่เพียงเพื่อให้เชื่อมต่อกับฐานข้อมูลบางครั้งก็แยกออกเพื่อใช้แบ็กเอนด์ฐานข้อมูลที่แตกต่างกัน

เซอร์วิสเลเยอร์อยู่ที่นั่นเพื่อจัดเตรียมตรรกะเพื่อดำเนินการกับข้อมูลที่ส่งไปยังและจาก DAO และไคลเอนต์ บ่อยครั้งที่ 2 ชิ้นเหล่านี้จะถูกรวมเข้าไว้ในโมดูลเดียวกันและบางครั้งก็เป็นรหัสเดียวกัน แต่คุณจะยังคงเห็นว่ามันเป็นเอนทิตีเชิงตรรกะที่แตกต่างกัน

อีกเหตุผลหนึ่งคือการรักษาความปลอดภัย - ถ้าคุณให้บริการเลเยอร์ที่ไม่มีความสัมพันธ์กับฐานข้อมูลการเข้าถึงฐานข้อมูลจากลูกค้าจะทำได้ยากกว่ายกเว้นผ่านบริการ หากฐานข้อมูลไม่สามารถเข้าถึงได้โดยตรงจากลูกค้า (และไม่มีโมดูล DAO เล็กน้อยที่ทำหน้าที่เป็นบริการ) จากนั้นผู้โจมตีทั้งหมดที่เข้ายึดลูกค้าสามารถทำได้คือพยายามแฮ็คชั้นบริการด้วยก่อนที่เขาจะได้รับทั้งหมด การเข้าถึงข้อมูลของคุณที่ถูกสุขอนามัยที่สุด


1
ฉันเห็นด้วยกับการแยกการบริการและเลเยอร์ dao และเลเยอร์บริการของคุณที่มีตรรกะทางธุรกิจของคุณ
Peter Delaney

ไม่ต้องพูดถึงว่า 1 บริการอาจเรียก DAO หลายตัวอย่างเช่นเมื่อบันทึกผู้ใช้ที่คุณอาจพูดคุยกับ UserDao, UserOrdersDao ฯลฯ หรือเราควรสร้างหนึ่งบริการสำหรับแต่ละ? แล้วใครจะเรียกบริการเหล่านี้ทั้งหมด
Fermin Silva

40

ฉันเป็นนักเขียนของโพสต์ที่เป็นปัญหา ฉันมีส่วนแบ่งที่ยุติธรรมในการทำงานกับเทคโนโลยีที่แตกต่างกันและสถาปัตยกรรมที่แตกต่างกัน จากข้างต้นฉันสามารถพูดได้อย่างปลอดภัยว่าการมีเลเยอร์บริการและเลเยอร์ dao นั้นเป็นความคิดที่ดีเสมอ DAO ควรถูก จำกัด ให้เพิ่ม / อัปเดต / แทรก / เลือกออบเจ็กต์เอนทิตีลงใน / จากฐานข้อมูลเท่านั้น หากคุณต้องการทำอะไรเพิ่มเติมในแง่ของตรรกะให้เพิ่มมันลงในเลเยอร์บริการ สิ่งนี้จะช่วยในการสร้างรหัสโมดูลาร์และสามารถเปลี่ยนได้ง่ายเมื่อมีการเปลี่ยนฐานข้อมูล (สำหรับบางส่วนของข้อมูล) สิ่งนี้สามารถใช้งานได้เป็นพิเศษในแอพพลิเคชั่นที่เกี่ยวข้องกับรายงานที่มี logics หนักแม้หลังจากดึงข้อมูลจากฐานข้อมูล

นอกจากนี้ในฤดูใบไม้ผลิการรักษาความปลอดภัยจะถูกนำไปใช้ในเลเยอร์บริการอย่างดีเลิศ คุณไม่ต้องการเปลี่ยนวิธีนี้


5
เฮ้ขอบคุณมากสำหรับการตอบคำถามของฉัน ที่อุทิศให้กับบล็อกของคุณ! ขอบคุณสำหรับตัวอย่างที่ยอดเยี่ยมเขียนต่อไป
Jeff

นี่เป็นการบั่นทอนจิตใจของฉันมาระยะหนึ่งแล้วและฉันคิดว่าประสบการณ์ช่วยได้มากที่สุดในสถานการณ์เหล่านี้ ขอขอบคุณ.
Utku Özdemir

ฉันเห็นด้วยกับการแยกการบริการและชั้น dao และชั้นบริการของคุณที่มีตรรกะทางธุรกิจของคุณและจะเรียกวิธีการ Dao เท่านั้น จะทำอย่างไรเมื่อหนึ่งในวิธีการบริการของฉันต้องเรียกวิธีการบริการอื่น ฉันควรจะมีสิ่งที่เป็นนามธรรมด้านบนเลเยอร์บริการที่เรียกวิธีการบริการหลายวิธีหรือไม่?
Peter Delaney

ไม่คลาสที่ชั้นบริการสามารถมีการอ้างอิงซึ่งกันและกัน (ตามต้องการ) และพวกเขาสามารถเรียกวิธีการที่จำเป็น
lokesh

11

อดัมเบียนชี้ให้เห็นในหนังสือของเขาว่าข้อเท็จจริงที่ว่า JPA EntityManager เป็นการนำ DAO ไปใช้อย่างเป็นสากล:

http://realworldpatterns.com/

ในโลก Java EE แทบจะไม่จำเป็นต้องเขียน DAO ของคุณเองเพราะการติดตั้ง JPA นั้นรวมอยู่ด้วย คุณจะต้องเขียนชั้นบริการ

การนำ DAO เลเยอร์ของคุณไปใช้จริง ๆ แล้วเป็นอาการเมาค้างจากสถาปัตยกรรม J2EE ที่แย่มากเมื่อ 15 ปีที่แล้ว แต่หลายคนยังรู้สึกว่าถูกบังคับให้ทำ เลเยอร์ DAO ที่กำหนดเองเหล่านี้มักจะให้อะไรมากกว่าฟังก์ชั่นการส่งต่อที่เรียกวิธีการที่สอดคล้องกันใน EntityManager

ดังนั้นเพื่อตอบคำถามของคุณใช่คุณต้องมีเลเยอร์บริการและ DAO แต่คุณต้องเขียนเลเยอร์บริการ


2
ผมไม่แน่ใจว่าที่นำไปใช้กับฤดูใบไม้ผลิ - มีเสมอ DAO ที่กำหนดเองที่ต้องทำสำหรับรุ่น คำแถลงของคุณอาจ "ไม่จำเป็นต้องเขียน DAO ของคุณเอง" ใช้กับ EJB คอนเทนเนอร์ / แอพพลิเคชันเซิร์ฟเวอร์โดยเฉพาะหรือไม่?
Don Cheadle

1
ดีกว่าที่จะเขียนของคุณเอง (DAO / DAOImpl) แม้ว่ามันจะแมปไป EntityManager - Thats เพราะในอนาคตคุณสามารถเพิ่มการดำเนิน DAO อื่นโดยไม่จำเป็นต้องเปลี่ยนรหัสชั้นบริการ
ahmednabil88

@YajliMaclo ความแตกต่างอะไรที่จะเปลี่ยน?
Alex78191

4

ฉันมักจะใส่รหัสเฉพาะ db (แบบสอบถาม) ทั้งหมดใน DAO และการจัดการธุรกรรมและตรรกะทางธุรกิจในการบริการ วิธีนี้ช่วยให้วิธีการบริการสามารถเรียกใช้วิธีการข้ามหลาย dao และเก็บไว้ในการทำธุรกรรมเดียวกัน ในความคิดของฉันนี้จะช่วยให้การใช้รหัสที่ดีขึ้นทั่ว dao ของ


2

ฉันพบว่าชั้นบริการเพิ่มความซับซ้อนที่ไม่จำเป็นในกรณีส่วนใหญ่ ในทางทฤษฎีคือการหลีกเลี่ยงที่จะมีตรรกะทางธุรกิจในเลเยอร์ dao แต่ท้ายที่สุดสิ่งนี้นำไปสู่ความสับสนแม้แต่บางคนก็ไม่ชอบที่จะลบเลเยอร์ dao อย่างสมบูรณ์เพราะพวกเขารู้สึกว่ามันไม่ได้เพิ่มมูลค่า http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer

แต่ถ้าคุณมีการบันทึกเชิงธุรกิจหลายครั้งใช่มันเป็นความคิดที่ดี การสร้างเลเยอร์บริการมีความสำคัญอย่างไร


3
ฉันได้อ่านบล็อกโพสต์ของ Ayende หลายครั้งแล้วและไม่สามารถสั่นคลอนความรู้สึกที่การออกแบบของเขา (ซึ่งฉันจะเห็นด้วยกับจุดหนึ่ง) ในขณะที่เป็นจริงกับจิตวิญญาณของ YAGNI เกือบจะหลีกเลี่ยงค่าใช้จ่าย dev เวลามากขึ้น ระยะกลางกว่าค่าใช้จ่ายในการตั้งค่านามธรรมของชั้นในสถานที่แรก ฉันสงสัยว่าเขาได้เปลี่ยนความเห็นของเขาเกี่ยวกับการมีเพศสัมพันธ์อย่างแน่นหนาระหว่างแอปพลิเคชันทั้งหมดและ NHibernate ในขณะนี้ว่ามันเป็นเรื่องธรรมดามากยิ่งขึ้นสำหรับแอปพลิเคชันเดียวเพื่อสอบถามแหล่งข้อมูล SQL, NoSQL และ API หลายแหล่ง
Mr Cochese

@LennyGodber ใช่ฉันรู้ว่าความรู้สึกของคุณ IMO ดีกว่าที่จะมีชั้น DAO / พื้นที่เก็บข้อมูลเพราะมันมีข้อได้เปรียบมากกว่าข้อเสียเพราะคุณบอกว่ามันเป็นเรื่องธรรมดามากที่จะมีแหล่งข้อมูลหลายแห่ง
Jesus

-1

IMHO ชั้นบริการถือได้ว่าเป็นชั้นระหว่างตัวควบคุมและชั้น DAO ชั้นบริการนี้เป็นที่ที่เราสามารถเพิ่มตรรกะทางธุรกิจและแม้กระทั่งสร้างวัตถุส่งคืนโดยเฉพาะกับสิ่งที่ต้องมีการแสดงผลโดยมุมมอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.