قبل وصف المشكلة، اسمحوا لي أن أشرح بعض المقدمات، لنفترض أنه تم تكوين معاملة قاعدة البيانات في ملف تكوين Spring بالطريقة التالية:
<bean id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven treatment-manager="transactionManager" />
الآن هناك UserDao وSecurityService:
@Repository public class UserDao { public User getUser() { // الاستعلام عن المستخدم من جدول المستخدم return queryObject("اختر * من طلب المستخدم حسب المعرف المحدد 1" } }
@Service @Transactional public class SecurityService { @Autowired Private UserDao userDao; public void checkUserInfo() { while(true) { User user = userDao.getUser(); if(user != null && "Tom".equals(user.getName ()) { System.out.println("توم هنا");
أثناء عملية استدعاء طريقة SecurityService#checkUserInfo()، تظل البيانات التي تم الحصول عليها من خلال طريقة userDao#getUser() دون تغيير. حتى إذا تم إدراج بيانات جديدة باسم Tom في هذا الوقت، فلن تنتهي الحلقة. بالإضافة إلى ذلك، لن تساعد إزالة التعليق التوضيحي @Transactional على SecurityService.
بادئ ذي بدء، اعتقدت أنه قد يكون هناك مشكلة في تجمع اتصال قاعدة البيانات، وينطبق الشيء نفسه عندما يتم استبداله بكائن Spring الخاص، ثم اتصلت بكائن الاتصال مباشرة من JdbcTemplate واستخدمت طريقة JDBC الأصلية لتشغيل قاعدة البيانات في هذا الوقت، كانت البيانات تتغير في الوقت الفعلي، لذلك اعتقدت أنه يجب أن تكون معاملة Spring مرتبطة بسلسلة العمليات الحالية. بعد التحقق من الكود المصدري، وجدت في طريقة DataSourceUtils#doGetConnection أن Spring أنشأ اتصالاً على كل مصدر بيانات لكل مؤشر ترابط وربطه بالمعاملة. نظرًا لأن ملف التكوين المستند إلى tx: annotation ينفذ ربط المعاملة على جميع طبقات الخدمة (الفئات الموضحة بـ @Service)، فإن نفس الاتصال مرتبط بنفس مؤشر الترابط بغض النظر عما إذا تم استخدام @Transactional، ولكن لا يتم تنفيذه فقط .
بعد العديد من التجارب والبحث عن المعلومات، وجدت أخيرًا الحل الأمثل: ما عليك سوى إضافة التعليق التوضيحي @Transactional(propagation = Propagation.NOT_SUPPORTED) إلى طريقة checkUserInfo أعلاه. بالطبع، يمكنك أيضًا الحصول على الاتصال وإجراء العملية يدويًا، أو يمكنك استخدام حزمة DateUtils لإجراء العملية.