ОБНОВЛЕНИЕ: ПРИМЕР УТОЧНИТЬ
Я собираюсь привести пример того, что происходит, чтобы прояснить ситуацию в моем приложении Spring + Hibernate.
Представьте, что у меня есть эти две сущности (предположим, существуют и геттеры и сеттеры)
@Entity
public class Class1(){
private Integer id;
@OneToOne
private Class2 object2;
}
@Entity
public class Class2(){
private Integer id;
@OneToOne
private Class1 object2;
}
Так что в моей базе данных у меня есть две таблицы для сопоставления каждого экземпляра каждого объекта. Предположим, я сохранил в базе данных эти объекты:
- objectA (класс Class1): id = 1, object2 = objectB
- objectB (класс Class2): id = 2, object2 = objectA
- objectC (класс Class2): id = 3, object2 = null
что означает, что A и 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);
восстановленный объект теперь:
- restoreObjectA (класс = класс1) id = 1, объект2 = объектC
хотя в базе есть:
- restoreObjectA (class = Class1) id = 1, object2 = objectB
Метод поиска не выполнил поиск в базе данных, и я получил предыдущий поиск, хотя у меня отключены кэши запросов и второго уровня. Метод find только отправляется в DAO, где он выполняется на entityManager.find (Class1.class, id)
Как мне сделать мой второй поиск в базе данных?
Спасибо
(полное объяснение)
Здравствуйте,
У меня есть приложение, которое использует Spring 3 и Hibernate. У меня есть объект с именем Class1, который хранится в базе данных. Этот объект имеет ссылку OneToOne на другой объект с именем Class2. Class2 имеет еще одну ссылку OneToOne на Class1, и обе ссылки имеют уникальное свойство, установленное в true.
У меня в контроллере следующий код:
//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);
Метод save в myService будет использовать менеджер сущностей для сохранения данных, но перед этим он проверит предыдущую связь между объектом Class1 и объектом Class2, чтобы удалить их, если новый объект Class2 установил экземпляр Class1. По этой причине я должен снова вызвать метод find, чтобы увидеть, что находится в моей базе данных
В службе:
@Transactional
public void save(Class1 object1){
Class1 objectFromDB = myDAO.find(object1.getId());
// .... update the old object and save
}
Проблема в том, что objectFromDB в Сервисе отличается от того, что было в myService.find (id) в контроллере. Проблема в том, что он не ищет его в базе данных, а ищет в памяти. Я знаю это, потому что при вызове второго метода find () не регистрируется оператор SQL. Так же, как я сделал setObject2 () для объекта storeData, я получаю именно этот объект, когда я вызываю метод find во второй раз, и база данных не содержит этого, поскольку он еще не был сохранен.
Я попытался отключить кэш в своей конфигурации, просто чтобы попробовать, но это все еще происходит. У меня есть ehCache с этой конфигурацией:
В persistence.xml у меня есть эти свойства (я установил в false оба кэша):
<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 в false, чтобы отключить его тоже.
Есть ли способ избежать этой ситуации?
Спасибо.