javax.transaction.Transactional vs org.springframework.transaction.annotation.Transactional


152

ฉันไม่เข้าใจความแตกต่างที่แท้จริงระหว่างคำอธิบายประกอบjavax.transaction.Transactionalและorg.springframework.transaction.annotation.Transactionalอะไร

คือorg.springframework.transaction.annotation.Transactionalการขยายjavax.transaction.Transactionalหรือพวกเขามีความหมายที่แตกต่างกันโดยสิ้นเชิง? เมื่อใดควรใช้แต่ละรายการ ฤดูใบไม้ผลิ@Transactinalในบริการชั้นและjavaxใน DAO?

ขอบคุณสำหรับคำตอบ.

คำตอบ:


125

Spring ได้กำหนดคำอธิบายประกอบธุรกรรมของตนเองเพื่อให้วิธีการทำธุรกรรม Spring bean เมื่อหลายปีก่อน

Java EE 7 ได้ทำสิ่งเดียวกันในที่สุดและตอนนี้อนุญาตให้วิธีการ CDI bean เป็นธุรกรรมนอกเหนือจากวิธี EJB ดังนั้นเนื่องจาก Java EE 7 จึงกำหนดคำอธิบายประกอบธุรกรรมของตนเอง (เห็นได้ชัดว่าไม่สามารถนำ Spring มาใช้ซ้ำได้)

ในแอปพลิเคชัน Java EE 7 คุณจะใช้คำอธิบายประกอบ Java EE

ในแอปพลิเคชัน Spring คุณจะใช้คำอธิบายประกอบของ Spring

การใช้งานของพวกเขาเหมือนกัน: แจ้งคอนเทนเนอร์ (Java EE หรือ Spring) ว่าเมธอดเป็นทรานแซคชัน


28
ยิ่งไปกว่านั้น: เพื่อที่จะปกครองจักรวาลสปริงยังได้เพิ่มการสนับสนุนโดยปริยายjavax.transaction.Transactionalดังนั้นใคร ๆ ก็สามารถใช้มันได้ในแอปพลิเคชันสปริงโดยไม่ต้องดำเนินการใด ๆ เพิ่มเติม IMO นี่เป็นการตัดสินใจที่ไม่ดีนักจากมุมมองการออกแบบเพราะจากประสบการณ์ของฉันผู้พัฒนาจำนวนมากสับสนโดยไม่รู้ตัวทั้งสองในรหัสของพวกเขาซึ่งนำไปสู่ปัญหาในภายหลัง
Yuriy Nakonechnyy

16
นอกจากนี้org.springframework.transaction.annotation.Transactionalตัวเลือกข้อเสนอมากขึ้น (เช่นreadOnly, timeoutกว่า)javax.transaction.Transactional
pierrefevrier

1
@ ยูระคุณสังเกตเห็นปัญหาอะไรบ้าง
Lee Chee Kiam

1
@LeeCheeKiam โปรดดูสองคำตอบด้านล่าง
Yuriy Nakonechnyy

50

ความแตกต่างก็คือวิธีที่ Spring จัดการกับคำอธิบายประกอบ @Transactional

  • org.springframework.transaction.annotation.Transactionalจะถูกนำมาพิจารณาเสมอ
  • javax.transaction.Transactionalถูกนำมาพิจารณาเฉพาะเมื่อมีการทำธุรกรรม EJB3 การแสดงตนของธุรกรรม EJB3 ทำได้โดยการตรวจสอบว่าคลาสjavax.ejb.TransactionAttributeนั้นมีอยู่ใน classpath หรือไม่ (จากรุ่น 2.5.3 ถึง 3.2.5) ดังนั้นคุณสามารถจบลงด้วยการเพิ่มความคิดเห็นของคุณโดยไม่คำนึงถึงเฉพาะjavax.transaction.Transactionalใน classpath ของคุณjavax.ejb.TransactionAttributeเท่านั้น นี้สามารถเป็นกรณีที่หากคุณกำลังทำงานกับ Hibernate: จำศีล-core (4.3.7.Final) ขึ้นอยู่กับ JBoss-ธุรกรรม api_1.2_spec (1.0.0.Final) javax.ejb.TransactionAttributeซึ่งไม่ได้ให้


มันไม่ได้เสมอถ้ามันเป็นวิธีส่วนตัวเช่นมันจะไม่ได้
ตี

36

โปรดระวัง (ปัญหานี้เกิดขึ้นในคราว)

หากแอปพลิเคชันของคุณคือเว็บแอปพลิเคชัน SPRING และคุณกำลังใช้กลไกการจัดการธุรกรรมของ Spring นั่นก็คือ @org.springframework.transaction.annotation.Transactionalอย่าผสมกับ javax.transaction.Transactional

ที่ใช้เสมอ @org.springframework.transaction.annotation.Transactionalในแอปพลิเคชันสปริงอย่างสม่ำเสมอ

มิฉะนั้นเราอาจท้ายด้วยข้อผิดพลาดนี้

org.springframework.orm.jpa.JpaSystemException: commit failed; nested exception is org.hibernate.TransactionException: commit failed

........

Caused by: java.sql.SQLException: Protocol violation: [0]

1
หมายเหตุ: คำตอบนี้เป็นกรณีพิเศษของคำตอบของฉัน
Jidehem

3

ขอบเขตธุรกรรมที่ประกาศ

ทั้ง@TransactionคำอธิบายประกอบSpring และ JPA ช่วยให้คุณสามารถกำหนดขอบเขตของธุรกรรมแอปพลิเคชันที่กำหนด

ดังนั้นหากวิธีการบริการได้รับการเพิ่มความคิดเห็นด้วยการเพิ่มความคิดเห็น@Transactionalมันจะทำงานในบริบทของการทำธุรกรรม หากวิธีการบริการใช้ DAO หรือที่เก็บหลายรายการการดำเนินการอ่านโฆษณาทั้งหมดจะถูกดำเนินการในธุรกรรมฐานข้อมูลเดียวกัน

ฤดูใบไม้ผลิ @Transactional

org.springframework.transaction.annotation.Transactionalคำอธิบายประกอบได้รับการบริการตั้งแต่รุ่น 1.2 ของกรอบฤดูใบไม้ผลิ (ประมาณ 2005) และมันช่วยให้คุณสามารถตั้งค่าคุณสมบัติการทำธุรกรรมต่อไปนี้:

  • isolation: ระดับการแยกฐานข้อมูลพื้นฐาน
  • noRollbackForและnoRollbackForClassName: รายการของExceptionคลาสJava ที่สามารถถูกทริกเกอร์โดยไม่ทริกเกอร์การย้อนกลับทรานแซคชัน
  • rollbackForและrollbackForClassName: รายการของExceptionคลาสJava ที่ทริกเกอร์การย้อนกลับของธุรกรรมเมื่อถูกส่งออกไป
  • propagation: ชนิดการเผยแพร่ธุรกรรมที่กำหนดโดยPropagationEnum ตัวอย่างเช่นถ้าบริบทการทำธุรกรรมสามารถสืบทอด (เช่นREQUIRED) หรือบริบทการทำธุรกรรมใหม่ควรจะสร้างขึ้น (เช่นREQUIRES_NEW) หรือถ้ามีข้อยกเว้นควรจะโยนถ้าไม่มีบริบทการทำธุรกรรมที่มีอยู่ (เช่นMANDATORY) หรือถ้าข้อยกเว้นควรจะโยน หากพบบริบทการทำธุรกรรมปัจจุบัน (เช่นNOT_SUPPORTED)
  • readOnly: ว่าธุรกรรมปัจจุบันควรอ่านข้อมูลโดยไม่ใช้การเปลี่ยนแปลงหรือไม่
  • timeout: บริบทการทำธุรกรรมควรได้รับอนุญาตให้เรียกใช้กี่วินาทีจนกว่าจะเกิดข้อยกเว้นการหมดเวลา
  • valueหรือtransactionManager: ชื่อของ Spring TransactionManagerbean ที่จะใช้เมื่อเชื่อมโยงบริบทการทำธุรกรรม

Java EE @Transactional

javax.transaction.Transactionalคำอธิบายประกอบถูกบันทึกโดย Java EE 7 สเปค (ประมาณ 2013) ดังนั้นการเพิ่มความคิดเห็น Java EE จึงเพิ่มขึ้น 8 ปีต่อมาว่า Spring

Java EE @Transactionalกำหนดเพียง 3 คุณลักษณะ:

  • dontRollbackOn: รายการของExceptionคลาสJava ที่สามารถทริกเกอร์ได้โดยไม่ทริกเกอร์การย้อนกลับทรานแซคชัน
  • rollbackOn: รายการExceptionคลาสJava ที่ทริกเกอร์การย้อนกลับธุรกรรมเมื่อถูกส่งออกไป
  • value: กลยุทธ์การขยายพันธุ์ที่กำหนดโดยTxTypeEnum ตัวอย่างเช่นถ้าบริบทการทำธุรกรรมสามารถสืบทอด (เช่นREQUIRED) หรือบริบทการทำธุรกรรมใหม่ควรจะสร้างขึ้น (เช่นREQUIRES_NEW) หรือถ้ามีข้อยกเว้นควรจะโยนถ้าไม่มีบริบทการทำธุรกรรมที่มีอยู่ (เช่นMANDATORY) หรือถ้าข้อยกเว้นควรจะโยน หากพบบริบทการทำธุรกรรมปัจจุบัน (เช่นNOT_SUPPORTED)

เลือกแบบไหน

หากคุณใช้ Spring หรือ Spring Boot ให้ใช้@TransactionalคำอธิบายประกอบของSpring เนื่องจากจะช่วยให้คุณสามารถกำหนดค่าแอตทริบิวต์ได้มากกว่า@TransactionalคำอธิบายประกอบJava EE

หากคุณใช้ Java EE เพียงอย่างเดียวและคุณปรับใช้แอปพลิเคชันของคุณบนเซิร์ฟเวอร์แอปพลิเคชัน Java EE ให้ใช้คำอธิบายประกอบ Java EE `` @ Transactional`

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการแตกต่างกันการกำหนดค่าระดับการแยกเมื่อใช้ฤดูใบไม้ผลิหรือ Java EE @Transactionalคำจำกัดความตรวจสอบบทความนี้

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