Hibernate постоянное поведение объекта - PullRequest
0 голосов
/ 19 ноября 2011

Я пытался узнать о различных состояниях объектов в Hibernate. Я попробовал следующее и не смог найти объяснения описанному поведению. Кто-нибудь может помочь?

Вот что я пытаюсь сделать: вставить новую запись в таблицу Employee (empId является первичным ключом). В той же транзакции обновите вновь добавленную запись (используя запрос, изменив empName). Затем, когда я проверяю свойство empName постоянного объекта, он продолжает показывать старое значение empName. Будучи постоянным объектом, я ожидал, что он будет отражать изменения, внесенные в базу данных. Я не мог понять, почему это не так. (В моем конфигурационном файле hibernate все установлено по умолчанию, за исключением свойства "hibernate.hbm2ddl.auto", установленного в качестве обновления) Однако после выполнения обновления, когда я устанавливаю empName постоянного объекта со значением, возвращаемым getEmpName (которое отображается как старое значение empName по sysout), в окончательных данных в таблице отображается новое значение empName (то есть то, которое я обновил с помощью HQL). Пожалуйста, обратитесь к коду для этого:

Transaction tx = session.getTransaction();
    tx.begin();

    Employee e1 = new Employee();
    e1.setEmpId(1);
    e1.setEmpName("Jack");
    e1.setEmpAge(25);
    session.save(e1);
    System.out.println("before: "+e1.getEmpName()); //prints Jack
    session.createQuery("update Employee set empName = \'Jack_new\' where id=1").executeUpdate();
    System.out.println("after: "+e1.getEmpName()); //prints Jack
    e1.setEmpName(e1.getEmpName()); //should update database
    tx.commit(); //sets empName value to Jack_new, as seen in table
    System.out.println("last: "+e1.getEmpName()); //prints Jack

Ответы [ 2 ]

5 голосов
/ 19 ноября 2011

С документация гибернации :

Управление данными непосредственно в базе данных (с использованием данных SQL Язык манипулирования (DML) операторы: INSERT, UPDATE, DELETE) не влияет на состояние в памяти.

Когда вы используете следующий прямой DML для обновления,

session.createQuery("update Employee set empName = \'Jack_new\' where id=1").executeUpdate();

он обходит контекст персистентности Hibernate (и все кэши). Таким образом, хотя empName является обновлением до Jack_new в БД, его экземпляр в контексте постоянства все еще сохраняет старое значение.

Вы можете использовать session.refresh(e1); для повторного считывания значений для e1 из базовой базы данных, так что e1.empName будет обновлено до Jack_new.

Обычно мы не пишем операторы UPDATE вручную для выполнения обновления. Просто установите обновленные значения в свойствах сохраняемых экземпляров. Во время очистки hibernate выполнит грязную проверку, автоматически сгенерирует и выдаст соответствующий SQL-код обновления, чтобы обновить эти грязные экземпляры.


(Ответ на комментарий):

Однако непосредственно перед выполнением tx.commit () я устанавливаю e1.empName в old значение (то есть значение, возвращаемое e1.getEmpName ()). Все еще последний в базе данных видно новое значение .?

/**e1 become persisted after save()**/
 session.save(e1);

/**e1.empName is updated to new value in the DB , but as the direct DML
 will not affect in-memory state , e1.empName in the java side 
 still keeps the old value***/
 session.createQuery("update Employee set empName = \'Jack_new\' where id=1").executeUpdate();

/** As you only set `e1.empName` to its original value , the values of `e1` do 
not have any changes. Thus , during the flushing (which occurs at the moment 
before `commit()`) , hibernate will consider  that `e1` is not dirty  and 
hence no update SQL will be generated and issued to update e1 . 
***/
e1.setEmpName(e1.getEmpName()); 

Итак, в результате Jack_new сохраняется в БД.

1 голос
/ 19 ноября 2011

вы выполняете прямой запрос к базе данных, изменяя значение поля за спиной hibernate. Когда вы сделаете это, ваш объект не будет волшебным образом изменять свое сохраненное значение, которое является исходным именем. Поэтому, когда вы делаете "e1.setEmpName (e1.getEmpName ());" Вы возвращаете имя к исходному значению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...