Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Сессия hibernate / 25 сообщений из 26, страница 1 из 2
29.03.2012, 01:56:43
    #37728700
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
При попытке обновления записи БД вываливается ошибка
Код: sql
1.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.hornsandhooves.db.entity.DivisionImpl#28]



Код упрошён, обёрнут в транзакцию - она получается у меня длинная.
Код: sql
1.
2.
3.
4.
5.
if(divisionDao.read(divisionForm.getId()) == null) {
            return false;
        } else {
divisionDao.getSession().update((DivisionImpl) division);
          return true;



Подскажите что нибудь по транзакциям и по сессии хибернеййта - как с этим бороться ?
...
Рейтинг: 0 / 0
29.03.2012, 01:58:00
    #37728701
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Прошу прощения - вот этот код, хотя разницы нет.

Код: sql
1.
2.
3.
4.
5.
if(divisionDao.read(divisionForm.getId()) == null) {
            return false;
        } else {
divisionDao.update((DivisionImpl) division);
          return true;
...
Рейтинг: 0 / 0
29.03.2012, 09:36:59
    #37728842
kiR@ch
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513,

А где division инициализируется? Думаю, дело в том, что сначала в division вытаскивается объект из БД, а потом вот в этой строке:
Код: java
1.
divisionDao.read(divisionForm.getId()


вы снова пытаетесь вытащить этот же объект. Из за этого возникает экспешн, который значит, что объект уже получен и связан с сессией.
...
Рейтинг: 0 / 0
29.03.2012, 11:38:34
    #37729109
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Вроде как не совсем так.. Т.е. происходит это в одной сессии и в одной транзакции. Как сделать это в одной транзакции - что бы не вываливался эксепшен ?

Мой DAO
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
public class DaoImpl <T, PK extends Serializable> implements IDao <T, PK> {
    
    private Class<T> type;
    
    @Autowired
    private SessionFactory sessionFactory;
    
    
    public DaoImpl(Class<T> type) {
        this.type = type;
    }
    
    public PK create(T o) {
        return (PK) getSession().save(o);
    }
    
    public T read(PK id) {
        return (T) getSession().get(type, id);
    }
    
    public void update(T o) {
        getSession().update(o);
    }
    
    public void delete(T o) {
        getSession().delete(o);
    }

    
    public List<T> findAll() {
        return  getSession().createQuery("from " + type.getName()).list();
    }
    
    /**
     * Возвращает текущую сессию hibernate
     * @return sessionFactory.getCurrentSession()
     */
    public Session getSession() {
        return sessionFactory.getCurrentSession();
    }
    
    public T getInstace() throws java.lang.InstantiationException, IllegalAccessException {
        return type.newInstance();
    }


DivisionDao
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
public class DivisionDao extends DaoImpl<DivisionImpl, Long> {
    
    /**
     * Конструктор инициализирует супер класс
     */
    public DivisionDao() {
        super(DivisionImpl.class);
    }
}
...
Рейтинг: 0 / 0
29.03.2012, 11:44:49
    #37729118
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513,

a different object with the same identifier value was already associated with the session

DivisionImpl division = read(id);
division.set();

divisionDao.getSession().update((DivisionImpl) division)

Условно, вы должны получить состояние объекта из базы, работать с ним, а потом делать апдейт.
У вас же получается :
-вы создаете новый объект
-получаете еще 1 объект (хотя и не явно) с тем же Id
-пытаетесь новый объект сделать update

Если я правильно понял всю проблему.
...
Рейтинг: 0 / 0
29.03.2012, 11:47:50
    #37729128
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513,
вариант без наследования (2-х классов) не рассматриваем? Т.к. у тебя тут в коде ничего нету на 50 строк imho
...
Рейтинг: 0 / 0
29.03.2012, 11:50:28
    #37729134
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Озверин,
да. У него 2 объекта и хибер почему-то не может сделать Merge.
И непонятно, нужны ли автору их 2 штуки....
(он сказал что БЛ длинная)
...
Рейтинг: 0 / 0
29.03.2012, 11:53:21
    #37729137
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Petro123,

я все еще не большой знаток, но учитывая текст ошибки, либо хибер и не должен никакого мерджа делать, либо не update надо вызывать ;)
...
Рейтинг: 0 / 0
29.03.2012, 11:53:38
    #37729138
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
"Условно, вы должны получить состояние объекта из базы, работать с ним, а потом делать апдейт." - т.е. если я правильно понял нужно сделать вот так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
IDivision division = divisionDao.read(divisionForm.getId());
if(division == null) {
    return false;
} else {
    division.setTitle(divisionForm.getTitle().trim().replaceAll("<", "&#60;"));
    divisionDao.getSession().update((DivisionImpl) division);
    return true;
...
Рейтинг: 0 / 0
29.03.2012, 11:56:10
    #37729142
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513,

да, как то так.
...
Рейтинг: 0 / 0
29.03.2012, 11:56:19
    #37729143
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Есть принципиальная разница между наследованием или нет ? И так и так я буду обращаться из транзакции к одной и той же сессии в DAO... если я правильно понимаю.
...
Рейтинг: 0 / 0
29.03.2012, 11:57:16
    #37729147
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
ОзверинPetro123,
я все еще не большой знаток, но учитывая текст ошибки, либо хибер и не должен никакого мерджа делать, либо не update надо вызывать ;)
я просто встречал этот код
Код: java
1.
2.
3.
if(division == null) {
    return false;
} else {


мне непонятно, почему при UPDATE записи в БД не нужно этого делать.
А при ОРМ нужно.
И неужели нельзя эту проверку убрать подальше (внутрь SaveOrUpdate).
...
Рейтинг: 0 / 0
29.03.2012, 11:58:21
    #37729150
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513Есть принципиальная разница между наследованием или нет ? И так и так я буду обращаться из транзакции к одной и той же сессии в DAO... если я правильно понимаю.
да. Это OFF\2
Просто, если в базовом классе нет логики, то он не нужен.
...
Рейтинг: 0 / 0
29.03.2012, 11:59:02
    #37729154
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
И ещё

[codde]
IDivision division = divisionDao.read(divisionForm.getId());
if(division == null) {
return false;
} else {
division.setTitle(divisionForm.getTitle().trim().replaceAll("<", "<"));
divisionDao.getSession().update((DivisionImpl) division);
return true;


Т.е если я изменяю прочитаный обьект .set(...) и даже не ложу его в .update(...) - это работает .
...
Рейтинг: 0 / 0
29.03.2012, 12:02:58
    #37729163
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Petro123 , в базовом классе реализован CRUD, что бы в дочерних классах, для остальных DAO его не реализовывать по многу раз, а далле в дочерние добавляется логика. Если я в каждом DAO реализую эти методы отдельно друг от друга - приложение будет вести себя по другому ? В моём понимании изменится только количество сессий..
...
Рейтинг: 0 / 0
29.03.2012, 12:05:42
    #37729168
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Проверку можно убрать дальше, но не хочется что бы бизнес логика была раскидана по всему приложению, если правильно понял вопрос.
...
Рейтинг: 0 / 0
29.03.2012, 12:06:00
    #37729170
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513И ещё

[codde]
IDivision division = divisionDao.read(divisionForm.getId());
if(division == null) {
return false;
} else {
division.setTitle(divisionForm.getTitle().trim().replaceAll("<", "<"));
divisionDao.getSession().update((DivisionImpl) division);
return true;


Т.е если я изменяю прочитаный обьект .set(...) и даже не ложу его в .update(...) - это работает .

Нет, вызывать таки я думаю надо;)
...
Рейтинг: 0 / 0
29.03.2012, 12:08:18
    #37729175
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Без вызова .update() работает )), ну можно конечно для красоты вызвать ). В общем ничего я не понимаю, что делать не знаю. Что почитать хоть посоветуйте.
...
Рейтинг: 0 / 0
29.03.2012, 12:09:28
    #37729177
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513Проверку можно убрать дальше, но не хочется что бы бизнес логика была раскидана по всему приложению, если правильно понял вопрос.
я спросил про длинные транзакции , но вы промолчали.
В общем случае, такая ошибка возникает когда вы деаттачите объект или закрываете сессию раньше времени. Потом меняете объект, но он "другой" и его надо мержить или через Lock.
Т.е. делайте короткие транзакции и следите чтобы объекты были не транзитными.
Т.е. imho мешанина кода на первый взгляд.
...
Рейтинг: 0 / 0
29.03.2012, 12:09:47
    #37729180
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Petro123ОзверинPetro123,
я все еще не большой знаток, но учитывая текст ошибки, либо хибер и не должен никакого мерджа делать, либо не update надо вызывать ;)
я просто встречал этот код
Код: java
1.
2.
3.
if(division == null) {
    return false;
} else {


мне непонятно, почему при UPDATE записи в БД не нужно этого делать.
А при ОРМ нужно.
И неужели нельзя эту проверку убрать подальше (внутрь SaveOrUpdate).

Тут подход все-таки немного другой.
Вопрос, который задает себе хибер, учитывая целостность данных:
-а как вы создали объект(насколько правильно?) , учитывая, что этот объект уже есть в базе данных?(если объект тривиальный, вам кажется и ответ простой, а если нет?)
-а почему вы его создали, а не получили из базы?
...
Рейтинг: 0 / 0
29.03.2012, 12:20:26
    #37729202
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Озверин-а почему вы его создали, а не получили из базы?
да. Я тебя понял. Либо объект деаттачили - оторвали от Хибера-БД и он не знает что с ним делать.
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Session session = sessionFactory1.openSession();
Transaction tx = session.beginTransaction();
Item item = (Item) session.get(Item.class, new Long(1234));
tx.commit();
session.close(); // end of first session, item is detached
 
item.getId(); // The database identity is "1234"
item.setDescription("my new description");
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
Item item2 = (Item) session2.get(Item.class, new Long(1234));
Item item3 = session2.merge(item); // Success!
tx2.commit();
session2.close();
...
Рейтинг: 0 / 0
29.03.2012, 12:23:18
    #37729211
alexander00513
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Petro123alexander00513Проверку можно убрать дальше, но не хочется что бы бизнес логика была раскидана по всему приложению, если правильно понял вопрос.
я спросил про длинные транзакции , но вы промолчали.
В общем случае, такая ошибка возникает когда вы деаттачите объект или закрываете сессию раньше времени. Потом меняете объект, но он "другой" и его надо мержить или через Lock.
Т.е. делайте короткие транзакции и следите чтобы объекты были не транзитными.
Т.е. imho мешанина кода на первый взгляд.

Мало что понял, т.к. новичок, если можно, разъясните пожалуйста. Я внутрь хибернэйта не залазил, работаю пока поверхностно, эксепшен явно связан с сессией, отсюда и пытаюсь разобраться. Когда этот код был написан в контроллере - он работал, всё проходило в разных транзакциях(чтение и обновление). Теперь же, мне в одной транзакции нужно проверить существует ли объект, потом принять данные пользователя, отвалидировать и обновить. Новый объект создаю из тех данных, которые получил от пользователя и пытаюсь положить его в метод .update(o)
...
Рейтинг: 0 / 0
29.03.2012, 12:24:02
    #37729212
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Озверин,
Получается, в общем случае:
- не писать if == nil
- не деаттачить объект или не работать с ним без сессии.
- если объект новый, то ...... проверьте ЭТО
...
Рейтинг: 0 / 0
29.03.2012, 12:29:08
    #37729220
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
alexander00513Теперь же, мне в одной транзакции нужно проверить существует ли объект, потом принять данные пользователя, отвалидировать и обновить. Новый объект создаю из тех данных, которые получил от пользователя
вот ЭТО проверь, что у тебя проходит в границах реквеста.
Т.е. короткие сессии = РеквестHTTP = Сессии Хибера = Транзакции Хибера.
Пока мысли такие.... imho
...
Рейтинг: 0 / 0
29.03.2012, 12:55:44
    #37729284
Озверин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сессия hibernate
Petro123Озверин,
Получается, в общем случае:
- не писать if == nil
- не деаттачить объект или не работать с ним без сессии.
- если объект новый, то ...... проверьте ЭТО

Непонятно ведь, откуда у нового объекта PK такой же, как у другого объекта ;)
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Сессия hibernate / 25 сообщений из 26, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]