سؤال

تحديث: مثال للتوضيح سأضع مثالاً على ما يحدث فقط لتوضيح الموقف في تطبيق الربيع + السبات. تخيل أن لدي هذين الكيانين (افترض أن getters و etters موجود أيضًا)

@Entity
public class Class1(){
  private Integer id;

  @OneToOne
  private Class2 object2;
}

@Entity
public class Class2(){
  private Integer id;

  @OneToOne
  private Class1 object2;
}

لذلك في قاعدة البيانات الخاصة بي ، لدي جدولين لرسم خريطة كل مثيل لكل كائن. لنفترض أنني قمت بتخزين في قاعدة البيانات هذه الكائنات:

  • Objecta (Class Class1): id = 1 ، Object2 = ObjectB
  • ObjectB (class2): id = 2 ، Object2 = Objecta
  • ObjectC (Class Class2): id = 3 ، Object2 = null مما يعني أن ANB B مرتبطة. افترض الآن أنني أريد ربط Objecta بـ ObjectC. هذا يعني أنني يجب أن أحذف الرابط في الكائن أيضًا.

للقيام بذلك ، أفعل العطل:

//I get the objectA from database
Class1 storedObjectA = myservice.find(objectAId);
//Now in storedObject1 I have the same as what it is stored as objectA

//I change only the object2 attribute of it
storedObject1.setObject2(objectC);

//I search again in the database to see objectA
Class1 reStoredObjectA = myservice.find(objectAId);

RestoredObjecta الآن هو:

  • RestoredObjecta (class = class1) id = 1 ، Object2 = ObjectC

على الرغم من أن هناك في قاعدة البيانات:

  • RestoredObjecta (class = class1) id = 1 ، Object2 = ObjectB

لم يتم البحث في Method Find في قاعدة البيانات وقد حصلت على البحث السابق على الرغم من أنني حصلت على استعلام وذاكرة التخزين المؤقت من المستوى الثاني. تذهب الطريقة التي تجدها فقط إلى DAO حيث يتم تنفيذها على EntityManager.find (class1.class ، id) كيف يمكنني إجراء عمليات البحث الثانية في قاعدة البيانات؟

شكرًا


(التفسير الكامل)

مرحبًا،

لدي تطبيق يستخدم Spring 3 و Hibernate. لدي كيان يدعى Class1 يتم تخزينه في قاعدة بيانات. يحتوي هذا الكيان على رابط OneToOne إلى كيان آخر يسمى Class2. يحتوي Class2 على رابط OneToOne آخر إلى Class1 ، وكلا الرابطين لهما خاصية فريدة من نوعها.

لدي الرمز التالي في وحدة التحكم الخاصة بي:

//I have an object called dataFromUser which is instance of Class1 and
// it is obtained via @ModelAttribute annotation from a form

Integer id = dataFromUser.getId();

//I get correctly the stored object from the database
Class1 storedData = myService.find(id); //this will call em.find of hibernate

//I set to the stored data the attribute I want to change
storedData.setObject2();

//I save again the object
myService.save(storedData);

ستستخدم Method in MyService مدير الكيان لاستمرار البيانات ، ولكن قبل ذلك ، سيتحقق من الارتباط السابق بين كائن Class1 وكائن Class2 لحذفه في حالة تعيين كائن Class2 جديد على مثيل Class1. لهذا السبب ، يجب أن أتصل بـ Find Method مرة أخرى لمعرفة ما هو موجود في قاعدة البيانات الخاصة بي

في الخدمة:

@Transactional
public void save(Class1 object1){
   Class1 objectFromDB =  myDAO.find(object1.getId());
   // ....  update the old object and save
}

المشكلة هي أن ObjectFromDB في الخدمة ليس هو نفسه كما لو كنت myservice.find (id) في وحدة التحكم. المشكلة هي أنها لا تبحث عنها في قاعدة البيانات ولكنها تبحث في الذاكرة. أعرف ذلك لأنه لا يوجد بيان SQL يتم تسجيله عند استدعاء طريقة Find () الثانية. نظرًا لأنني قمت بـ setObject2 () على كائن StoredData ، أحصل على هذا الكائن بالضبط عندما أتصل بـ Find Method للمرة الثانية ، ولا تحتوي قاعدة البيانات على هذا لأنه لم يتم استمراره بعد.

لقد حاولت تعطيل ذاكرة التخزين المؤقت في تكوينتي لمجرد المحاولة ، لكنها لا تزال تحدث. لدي ehcache مع هذا التكوين:

في pressustence.xml لدي هذه الخصائص (لقد ضبطت على كلا من ذاكرة التخزين المؤقت):

    <properties>
     <!-- Hibernate 3.5.0 - try org.hibernate.cache.* package -->
  <property name="hibernate.cache.provider_class"
               value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
   <property name="hibernate.cache.use_query_cache" value="false" />
  <property name="hibernate.cache.use_second_level_cache" value="false" />
  <property name="hibernate.generate_statistics" value="true" />
  <property name="hibernate.cache.use_structured_entries" value="false" />
  <property name="hibernate.format_sql" value="true" />
  <!-- http://www.jroller.com/eyallupu/entry/hibernate_s_hbm2ddl_tool -->
  <!-- create, create-drop, update, validate -->
  <property name="hibernate.hbm2ddl.auto" value="update" />
    </properties>  

في ehcache.xml ، قمت بتعيين على 0 maxElementSinMemory و OverflowTodisk لخطأ لتعطيله أيضًا.

هل هناك أي طريقة لتجنب هذا الموقف؟

شكرًا.

هل كانت مفيدة؟

المحلول 2

حسنًا ، أجدها. المشكلة هي أن السبات يبحث عن الكائنات في جلستها قبل البحث في قاعدة البيانات. لذلك اضطررت إلى فصل الكائن إلى الجلسة قبل تعديله. للقيام بذلك في السبات:

    //being em my EntityManager instance
    Session session = (Session) em.getDelegate();
    session.evict(plan); 
    //Now the find object will not get the object wich is in session 
    //but the one in database

نصائح أخرى

لست متأكدًا من فهمني بشكل صحيح ، ولكن فقط في حالة ...


هناك طريقتان لتحميل كائن. هناك فرق إذا لم يكن الكائن في سياق الذاكرة الحالي:

  • يذهب المرء بالتأكيد إلى قاعدة البيانات ، وإرجاع المثيل إذا كان موجودًا أو لاغية خلاف ذلك.
  • الآخر يخلق مجرد وكيل مع المعرف الصحيح ، دون الانتقال فورًا إلى قاعدة البيانات ، وسيقوم بمعالجته كما هو مطلوب في العمليات اللاحقة (ربما عند التدفق).

يبدو أنك تستخدم الثانية ، ربما يمكنك تجربة الأول ومعرفة ما إذا كان يحل مشكلتك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top