1. ภาพรวม
บทช่วยสอนนี้จะกล่าวถึงวิธีที่ถูกต้องในการกำหนดค่าธุรกรรมในช่วงฤดูใบไม้ผลิวิธีใช้คำอธิบายประกอบ@Transactionalและข้อผิดพลาดทั่วไป
สำหรับการสนทนาเชิงลึกเพิ่มเติมเกี่ยวกับการกำหนดค่าการคงอยู่หลักโปรดดูบทช่วยสอน Spring with JPA
โดยทั่วไปมีสองวิธีที่แตกต่างกันในการกำหนดค่าธุรกรรม - คำอธิบายประกอบและ AOP แต่ละวิธีมีข้อดีของตัวเอง เราจะพูดถึงการกำหนดค่าคำอธิบายประกอบทั่วไปที่นี่
2. กำหนดค่าธุรกรรม
ฤดูใบไม้ผลิ 3.1 แนะนำ@EnableTransactionManagementบันทึกย่อที่เราสามารถใช้ใน@Configurationระดับและเปิดใช้งานการสนับสนุนการทำธุรกรรม:
@Configuration @EnableTransactionManagement public class PersistenceJPAConfig{ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){ //... } @Bean public PlatformTransactionManager transactionManager(){ JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory( entityManagerFactoryBean().getObject() ); return transactionManager; } }
แต่ถ้าเรากำลังใช้โครงการ Boot ฤดูใบไม้ผลิและมีฤดูใบไม้ผลิ DATA- * หรือฤดูใบไม้ผลิ-TX อ้างอิงใน classpath แล้วจัดการการทำธุรกรรมจะเปิดใช้งานโดยค่าเริ่มต้น
3. กำหนดค่าธุรกรรมด้วย XML
ก่อน 3.1 หรือถ้า Java ไม่ใช่อ็อพชันนี่คือคอนฟิกูเรชัน XML โดยใช้คำอธิบายประกอบเป็นตัวขับเคลื่อนและการสนับสนุนเนมสเปซ:
4. คำอธิบายประกอบ@Transactional
ด้วยการกำหนดค่าธุรกรรมตอนนี้เราสามารถใส่คำอธิบายประกอบ bean ด้วย@Transactional ได้ทั้งในระดับคลาสหรือวิธีการ:
@Service @Transactional public class FooService { //... }
คำอธิบายประกอบรองรับการกำหนดค่าเพิ่มเติมเช่นกัน:
- การขยายพันธุ์ประเภทของการทำธุรกรรม
- ระดับการแยกของการทำธุรกรรม
- หมดเวลาสำหรับการดำเนินงานห่อโดยการทำธุรกรรม
- ธงอ่านได้อย่างเดียว - คำแนะนำสำหรับผู้ให้บริการการติดตาว่าการทำธุรกรรมที่ควรจะอ่านอย่างเดียว
- ย้อนกลับกฎสำหรับการทำธุรกรรม
โปรดทราบว่าโดยค่าเริ่มต้นการย้อนกลับจะเกิดขึ้นสำหรับรันไทม์ยกเว้นที่ไม่ได้เลือกเท่านั้น ข้อยกเว้นที่ตรวจสอบไม่ได้ทำให้เกิดการย้อนกลับของธุรกรรม แน่นอนเราสามารถกำหนดค่าลักษณะการทำงานนี้ด้วยพารามิเตอร์rollbackForและnoRollbackFor annotation
5. ข้อผิดพลาดที่อาจเกิดขึ้น
5.1. ธุรกรรมและผู้รับมอบฉันทะ
ในระดับสูงSpring จะสร้างพร็อกซีสำหรับคลาสทั้งหมดที่ใส่คำอธิบายประกอบด้วย@Transactional - ไม่ว่าจะในคลาสหรือวิธีใดก็ได้ พร็อกซีอนุญาตให้เฟรมเวิร์กฉีดลอจิกทรานแซคชันก่อนและหลังวิธีการทำงาน - ส่วนใหญ่สำหรับการเริ่มต้นและการทำธุรกรรม
สิ่งสำคัญที่ต้องจำไว้คือหาก Transactional bean กำลังใช้งานอินเทอร์เฟซโดยค่าเริ่มต้นพร็อกซีจะเป็น Java Dynamic Proxy ซึ่งหมายความว่าเฉพาะการเรียกเมธอดภายนอกที่เข้ามาผ่านพร็อกซีเท่านั้นที่จะถูกดักฟัง การเรียกด้วยตนเองจะไม่เริ่มต้นธุรกรรมใด ๆแม้ว่าเมธอดนั้นจะมีคำอธิบายประกอบ@Transactionalก็ตาม
ข้อแม้อีกประการหนึ่งของการใช้พร็อกซีคือเฉพาะเมธอดสาธารณะเท่านั้นที่ควรใส่คำอธิบายประกอบด้วย@Transactional วิธีการมองเห็นอื่น ๆ จะเพิกเฉยต่อคำอธิบายประกอบอย่างเงียบ ๆ เนื่องจากไม่ได้รับมอบฉันทะ
บทความนี้กล่าวถึงข้อผิดพลาดในการพร็อกซีเพิ่มเติมโดยละเอียดที่นี่
5.2. การเปลี่ยนระดับการแยก
นอกจากนี้เรายังสามารถเปลี่ยนระดับการแยกธุรกรรม:
@Transactional(isolation = Isolation.SERIALIZABLE)
โปรดทราบว่าสิ่งนี้ถูกนำมาใช้จริงใน Spring 4.1; หากเราเรียกใช้ตัวอย่างข้างต้นก่อนฤดูใบไม้ผลิ 4.1 จะส่งผลให้:
org.springframework.transaction.InvalidIsolationLevelException : มาตรฐาน JPA ไม่รองรับระดับการแยกที่กำหนดเอง - ใช้JpaDialectพิเศษสำหรับการใช้งาน JPA ของคุณ
5.3. ธุรกรรมอ่านอย่างเดียว
อ่านได้อย่างเดียวธงมักจะสร้างความสับสนโดยเฉพาะอย่างยิ่งเมื่อทำงานกับ JPA; จาก Javadoc:
นี่เป็นเพียงคำใบ้สำหรับระบบย่อยธุรกรรมจริง มันจะไม่จำเป็นต้องทำให้เกิดความล้มเหลวของความพยายามในการเข้าถึงการเขียน ตัวจัดการธุรกรรมที่ไม่สามารถตีความคำใบ้แบบอ่านอย่างเดียวจะไม่เกิดข้อยกเว้นเมื่อถูกถามถึงธุรกรรมแบบอ่านอย่างเดียว
ความจริงก็คือเราไม่สามารถมั่นใจได้ว่าการแทรกหรือการอัปเดตจะไม่เกิดขึ้นเมื่อตั้งค่าสถานะreadOnly พฤติกรรมนี้ขึ้นอยู่กับผู้ขายในขณะที่ JPA เป็นผู้ขายที่ไม่เชื่อเรื่องพระเจ้า
นอกจากนี้ยังเป็นสิ่งสำคัญที่จะเข้าใจว่าอ่านได้อย่างเดียวธงเป็นเพียงที่เกี่ยวข้องภายในการทำธุรกรรม หากการดำเนินการเกิดขึ้นนอกบริบทธุรกรรมแฟล็กจะถูกละเว้น ตัวอย่างง่ายๆที่จะเรียกวิธีการที่มีคำอธิบายประกอบ:
@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )
จากบริบทที่ไม่ใช่ธุรกรรม - ธุรกรรมจะไม่ถูกสร้างขึ้นและแฟล็ก readOnlyจะถูกละเว้น
5.4. การบันทึกธุรกรรม
วิธีที่เป็นประโยชน์ในการทำความเข้าใจปัญหาที่เกี่ยวข้องกับธุรกรรมคือการปรับแต่งการบันทึกในแพ็คเกจธุรกรรม แพ็กเกจที่เกี่ยวข้องใน Spring คือ " org.springframework.transaction" ซึ่งควรกำหนดค่าด้วยระดับการบันทึกของ TRACE
6. บทสรุป
เราได้กล่าวถึงการกำหนดค่าพื้นฐานของความหมายของธุรกรรมโดยใช้ทั้ง Java และ XML วิธีใช้@Transactionalและแนวทางปฏิบัติที่ดีที่สุดของกลยุทธ์การทำธุรกรรม
เช่นเคยรหัสที่นำเสนอในบทความนี้มีอยู่ใน Github