powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Сессия hibernate
25 сообщений из 26, страница 1 из 2
Сессия hibernate
    #37728700
alexander00513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При попытке обновления записи БД вываливается ошибка
Код: 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
Сессия hibernate
    #37728701
alexander00513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прошу прощения - вот этот код, хотя разницы нет.

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

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


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

Мой 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
Сессия hibernate
    #37729118
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Сессия hibernate
    #37729128
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexander00513,
вариант без наследования (2-х классов) не рассматриваем? Т.к. у тебя тут в коде ничего нету на 50 строк imho
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729134
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Озверин,
да. У него 2 объекта и хибер почему-то не может сделать Merge.
И непонятно, нужны ли автору их 2 штуки....
(он сказал что БЛ длинная)
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729137
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123,

я все еще не большой знаток, но учитывая текст ошибки, либо хибер и не должен никакого мерджа делать, либо не update надо вызывать ;)
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729138
alexander00513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
"Условно, вы должны получить состояние объекта из базы, работать с ним, а потом делать апдейт." - т.е. если я правильно понял нужно сделать вот так:
Код: 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
Сессия hibernate
    #37729142
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexander00513,

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


мне непонятно, почему при UPDATE записи в БД не нужно этого делать.
А при ОРМ нужно.
И неужели нельзя эту проверку убрать подальше (внутрь SaveOrUpdate).
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729150
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexander00513Есть принципиальная разница между наследованием или нет ? И так и так я буду обращаться из транзакции к одной и той же сессии в DAO... если я правильно понимаю.
да. Это OFF\2
Просто, если в базовом классе нет логики, то он не нужен.
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729154
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
Сессия hibernate
    #37729163
alexander00513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Petro123 , в базовом классе реализован CRUD, что бы в дочерних классах, для остальных DAO его не реализовывать по многу раз, а далле в дочерние добавляется логика. Если я в каждом DAO реализую эти методы отдельно друг от друга - приложение будет вести себя по другому ? В моём понимании изменится только количество сессий..
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729168
alexander00513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Проверку можно убрать дальше, но не хочется что бы бизнес логика была раскидана по всему приложению, если правильно понял вопрос.
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729170
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Сессия hibernate
    #37729175
alexander00513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Без вызова .update() работает )), ну можно конечно для красоты вызвать ). В общем ничего я не понимаю, что делать не знаю. Что почитать хоть посоветуйте.
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729177
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexander00513Проверку можно убрать дальше, но не хочется что бы бизнес логика была раскидана по всему приложению, если правильно понял вопрос.
я спросил про длинные транзакции , но вы промолчали.
В общем случае, такая ошибка возникает когда вы деаттачите объект или закрываете сессию раньше времени. Потом меняете объект, но он "другой" и его надо мержить или через Lock.
Т.е. делайте короткие транзакции и следите чтобы объекты были не транзитными.
Т.е. imho мешанина кода на первый взгляд.
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729180
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123ОзверинPetro123,
я все еще не большой знаток, но учитывая текст ошибки, либо хибер и не должен никакого мерджа делать, либо не update надо вызывать ;)
я просто встречал этот код
Код: java
1.
2.
3.
if(division == null) {
    return false;
} else {


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

Тут подход все-таки немного другой.
Вопрос, который задает себе хибер, учитывая целостность данных:
-а как вы создали объект(насколько правильно?) , учитывая, что этот объект уже есть в базе данных?(если объект тривиальный, вам кажется и ответ простой, а если нет?)
-а почему вы его создали, а не получили из базы?
...
Рейтинг: 0 / 0
Сессия hibernate
    #37729202
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Озверин-а почему вы его создали, а не получили из базы?
да. Я тебя понял. Либо объект деаттачили - оторвали от Хибера-БД и он не знает что с ним делать.
Код: 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
Сессия hibernate
    #37729211
alexander00513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Petro123alexander00513Проверку можно убрать дальше, но не хочется что бы бизнес логика была раскидана по всему приложению, если правильно понял вопрос.
я спросил про длинные транзакции , но вы промолчали.
В общем случае, такая ошибка возникает когда вы деаттачите объект или закрываете сессию раньше времени. Потом меняете объект, но он "другой" и его надо мержить или через Lock.
Т.е. делайте короткие транзакции и следите чтобы объекты были не транзитными.
Т.е. imho мешанина кода на первый взгляд.

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

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


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