powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Помогите разобраться с сессиями Hibernate
23 сообщений из 23, страница 1 из 1
Помогите разобраться с сессиями Hibernate
    #38616654
JulT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть фабрика по созданию сессии:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
public class HibernateUtil {

    private static final SessionFactory sessionFactory;
  
    static {
        try {
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}


Есть класс LigaDAO:

Код: java
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.
public class LigaDAO {
    
Session currentSession() {
        return HibernateUtil.getSessionFactory().getCurrentSession();
    }

public void addOrUpdateLiga(Liga liga) {
            try {
              
                currentSession().beginTransaction();
                
                  if(liga.getId()!=null){
                     // update
                     currentSession().merge(liga);     
                   }else{
                     // insert  
                     currentSession().save(liga);  
                   }
                  
                  currentSession().getTransaction().commit();
                  
            } catch (Exception e) {
                  e.printStackTrace();
            }
    }
}


В двух разных браузерах пользователь открывает сущность Liga с id=2, первый пользователь удаляет запись, у второго она продолжает висеть на экране. Далее, второй пользователь сохраняет висящую на экране запись. В результате вызывается метод addOrUpdateLiga и в базе снова появляется объект Liga, который идентичен удаленному по всем полям кроме id. Как такие ситуации разрешаются? Это первый вопрос. Второй: как правильно реализовывать работу с сессиями Hibernate в веб-приложениях? необходимо открывать-закрывать сессию для каждого действия или как?
Спасибо
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38616679
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не надо делать addOrUpdate. Надо делать только Update. И тогда хибернейт заругается, что сущности уже нет (удалена) и не сохранит её снова. Ексепшн из хиберейта поймать и показать юзеру в браузере в виде вменяемого сообщения (окошко там всплывающее и т.д.)
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617079
JulT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For AllНе надо делать addOrUpdate. Надо делать только Update. И тогда хибернейт заругается, что сущности уже нет (удалена) и не сохранит её снова. Ексепшн из хиберейта поймать и показать юзеру в браузере в виде вменяемого сообщения (окошко там всплывающее и т.д.)
Сделала 2 метода:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public void updateLiga(Liga liga) throws Exception{
            try {
                currentSession().beginTransaction();
                
                currentSession().update(liga);
                  
                currentSession().getTransaction().commit();
            } catch (Exception e) {
                throw e;
            } 
    }


и второй:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public void insertLiga(Liga liga) throws Exception{
            try { 
                currentSession().beginTransaction();
                 
                currentSession().save(liga);
               
                currentSession().getTransaction().commit();
                  
            } catch (Exception e) {
                 throw e;
            } 
    }


Вызываю их следующим образом:
Код: java
1.
2.
3.
4.
5.
if(selectLiga.getId()!=null){
                 Factory.getInstance().getLigaDAO().updateLiga(selectLiga); 
              }else{
                  Factory.getInstance().getLigaDAO().insertLiga(selectLiga);  
   }


Сделала удаление в одном браузере, в другом пытаюсь изменить, выскакивает ошибка:
Код: java
1.
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1


Не могу понять, это и есть тот самый эксепшн, который означает, что сущности уже нет (удалена)??
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617238
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulTВторой: как правильно реализовывать работу с сессиями Hibernate в веб-приложениях? необходимо открывать-закрывать сессию для каждого действия или как?
есди без спринга то
Код: java
1.
2.
3.
4.
5.
6.
protected void doGet(HttpServletRequest request, HttpServletResponse response)
	  открыли сессию хибера в потоке
	  поработали
	  writer.write("<h1>Welcome to Hell</h1>");
	  закрыли
	}


всю остальную лабуду спрятать в
Код: java
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.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
package dao;

import main.Main;// пакет с DAO

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

public class HibernateUtil {
	private static SessionFactory factory;

	public static Configuration getInitializedConfiguration() {
		AnnotationConfiguration config = new AnnotationConfiguration();
		/* !!!!!!!!!!!!!!   // пакет с DAO */
		config.addAnnotatedClass(Book.class);
		config.addAnnotatedClass(Autor.class);
		config.configure();
		return config;
	}

	public static Session getSession() {
		if (factory == null) {
			Configuration config = HibernateUtil.getInitializedConfiguration();
			factory = config.buildSessionFactory();
		}
		Session hibernateSession = factory.getCurrentSession();
		return hibernateSession;
	}

	public static void closeSession() {
		HibernateUtil.getSession().close();
	}

	public static void recreateDatabase() {
		Configuration config;
		config = HibernateUtil.getInitializedConfiguration();
		new SchemaExport(config).create(true, true);
	}

	public static Session beginTransaction() {
		Session hibernateSession;
		hibernateSession = HibernateUtil.getSession();
		hibernateSession.beginTransaction();
		return hibernateSession;
	}

	public static void commitTransaction() {
		HibernateUtil.getSession().getTransaction().commit();
	}

	public static void rollbackTransaction() {
		HibernateUtil.getSession().getTransaction().rollback();
	}

	public static void main(String args[]) {
		HibernateUtil.recreateDatabase();
	}

}

...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617365
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulTСделала удаление в одном браузере, в другом пытаюсь изменить, выскакивает ошибка:
Код: java
1.
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1


Не могу понять, это и есть тот самый эксепшн, который означает, что сущности уже нет (удалена)??Именно он: под катом хибернейт выполняет SQL-команду UРDATE (с условием типа WHERE ID=#value) через JDBC метод Statement.executeUpdate . Этот метод возвращает int - количество проапдейченых строк в базе. Хибернейт знает, что он апдейтит одну сущность (читай одну строку), а вот база по тому условию WHERE ни одной строки не находит и не апдейтит и, соответственно, метод executeUpdate возвращает 0. Хибернейт из-за этого несоответсвия ожидаемого и полученно бросает ексепшен, в тексте которого так и написано:
returned unexpected row count from update [0]; actual row count: 0; expected: 1
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617385
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMHO, надо с начала расписаьб бизнес-логику и утвердить ее, а потом делать согласно ей.

Что-нибудь на вроде.
При сохранении ранее считанной и измененной записиь делаем:
1. Заблокировали запись если есть.
2. Если записи нет - то ...
3. Если заблокировать не удалось то ...
4. Проверяем не изменилась ли запись кем-то еще.
5. Если запись изменилась то ...
6. Если не изменилась то update.

И с Hibernate будет разобраться намного легче.
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617438
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевIMHO, надо с начала расписаьб бизнес-логику и утвердить ее, а потом делать согласно ей.

Что-нибудь на вроде.
При сохранении ранее считанной и измененной записиь делаем:
1. Заблокировали запись если есть.
2. Если записи нет - то ...
3. Если заблокировать не удалось то ...
4. Проверяем не изменилась ли запись кем-то еще.
5. Если запись изменилась то ...
6. Если не изменилась то update.

И с Hibernate будет разобраться намного легче.
Вся эта логика уже реализована хибернейтом и писать её самому заново совершенно нет необходимости.
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617647
JulT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем огромное спасибо за советы.
Я вот еще чего не могу понять. Вот код одного из моих методов:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
 public void updateLiga(Liga liga) throws Exception{
            try {
                currentSession().beginTransaction();
                
                currentSession().update(liga);
                  
                currentSession().getTransaction().commit();
            } catch (Exception e) {
                throw e;
            } 
    }


Нужно ли в нем закрывать сессию, или после коммита она закрывается самостоятельно? Когда добавляю к этому методу это:
Код: java
1.
2.
3.
4.
5.
} finally {
                if (currentSession() != null && currentSession().isOpen()) {
                    currentSession().close();
                }
            }


В другом месте ругается на то, что я пытаюсь работать с закрытой сессией.
вот метод по получению сессии:
Код: java
1.
2.
3.
Session currentSession() {
        return HibernateUtil.getSessionFactory().getCurrentSession();
    }



И еще вопрос. Не могу понять когда в каком случае нужно очищать сессию и нужно ли делать это вообще? Про кеши 1,2 уровней и кеш запросов - читала. Задаю много вопросов т.к. хочется докопаться до сути, так что сорри :).
Спасибо!
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617676
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For AllВся эта логика уже реализована хибернейтом
Я рад, что Hibernate думает за Вас, но написать на бумаге, что именно надо делать в случаях, которые отмечены ... , все равно не помешает.
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617685
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulTВсем огромное спасибо за советы.
Я вот еще чего не могу понять. Вот код одного из моих методов:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
 public void updateLiga(Liga liga) throws Exception{
            try {
                currentSession().beginTransaction();
                
                currentSession().update(liga);
                  
                currentSession().getTransaction().commit();
            } catch (Exception e) {
                throw e;
            } 
    }



Простите, а вызов метода currentSession каждый раз, это сделано в ожидании, что вдруг в следующий раз это будет другая сессия?
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617703
JulT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев,
нет, нужно было так сразу написать:
Session sess=currentSession();
sess.beginTransaction();

sess.save(liga);

sess.getTransaction().commit();
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617722
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulT,

1. currentSession может и не быть.
2. Она может не открыться и пр.

новомодно писать, что-то типа

Код: java
1.
try (Connection conn = ...) {
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617724
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев,

В смысле Session sess = ...
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617741
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulTНужно ли в нем закрывать сессию, или после коммита она закрывается самостоятельно?Думаю, что не стоит: управление currentSession() инкапсулировано в конкретной реализации CurrentSessionContext -е, а он может быть разный в зависимости от того standalone приложение это или внутри какого-нибудь application server-а (типа jboss) крутится.

JulTИ еще вопрос. Не могу понять когда в каком случае нужно очищать сессию и нужно ли делать это вообще? Про кеши 1,2 уровней и кеш запросов - читала. Задаю много вопросов т.к. хочется докопаться до сути, так что сорри :).
Спасибо!Кеш 1-го уровня (транзакционный) очищается каждый раз хибернейтом во время коммита/отката транзакции.

Кеш 2-го уровня живёт дольше транзакций и педназначен для того чтобы не лезть каждый раз в базу (например 50 запросов в секунду к одной и той же таблице, а данные в таблице меняется раз в неделю - нет смысла на каждый запрос лезть в базу за данными, лучше закешировать в памяти и брать оттуда - быстрее). Минус кеша 2-го уровна в том, что если базу проапдейтит кто-то со стороны (в обход хибернейта) то кеш эти апдейты не увидит и будт продолжать отдавать закешированные старые записи.
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38617886
JulT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо всем за ответы.
Я использую thread контекст: <property name="current_session_context_class">thread</property>
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618145
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulTВ другом месте ругается на то
В каком именно другом месте.
Я не очень верю в "универсальный код для разных мест".
Т.е. нужен контекст применения Вами хибера......функция main....сервлет или ещё что....

JulTСпасибо всем за ответы.
Я использую thread контекст: <property name="current_session_context_class">thread</property>
это значит что вы не выходя из потока должны получить сессию хибера (а не БД), использовать и закрыть.
Если это сервлет, то за доли секунды пока идёт вызов сервлета. Т.к. он может быть в потоке.
15894711
В десктопе всё по другому.
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618199
JulT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123JulTВ другом месте ругается на то
В каком именно другом месте.
Я не очень верю в "универсальный код для разных мест".
Т.е. нужен контекст применения Вами хибера......функция main....сервлет или ещё что....

JulTСпасибо всем за ответы.
Я использую thread контекст: <property name="current_session_context_class">thread</property>
это значит что вы не выходя из потока должны получить сессию хибера (а не БД), использовать и закрыть.
Если это сервлет, то за доли секунды пока идёт вызов сервлета. Т.к. он может быть в потоке.
15894711
В десктопе всё по другому.
Вот здесь http://j4sq.blogspot.com/2011/09/hibernate-reference-manual.html?m=1 вычитала следующее:
По умолчанию метод commit() автоматически закрывает сессию, и при следующем обращении к getCurrentSession будет создана новая, так что делать close() или disconnect() не нужно.
Как понять?
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618340
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulT,
попробуйте так. Я предпочитаю минимум шума-кода на экране (10 строк) по ООП и здравому смыслу.
Код: java
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.
45.
46.
47.
48.
49.
50.
package main;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.hibernate.Session;

import dao.HibernateUtil;

@Entity
public class Main {
	private int id;
	private String password;

	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public static void main(String[] args) {
		System.out.println("Start Main V");
		// HibernateUtil.recreateDatabase(); //ПЕРЕСОЗДАЁТ ТАБЛИЧКИ В БД !!!
		Session session = HibernateUtil.beginTransaction(); // автостарт сессии -
																												// current_session_context_class
		try {
			System.out.println("Создать класс-запись в БД");
			Main u = new Main();
			u.setPassword("abc123");
			session.saveOrUpdate(u);
			System.out.println("Сохранили в БД класс без коммита");
		} finally {
			HibernateUtil.commitTransaction();
			System.out.println("Коммит прошёл. Всё");
		}
	}
}
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618349
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: java
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.
	public static Session getSession() {
		if (factory == null) {
			Configuration config = HibernateUtil.getInitializedConfiguration();
			factory = config.buildSessionFactory();
		}
		Session hibernateSession = factory.getCurrentSession();
		return hibernateSession;
	}

	public static void closeSession() {
		HibernateUtil.getSession().close();
	}

	public static void recreateDatabase() {
		Configuration config;
		config = HibernateUtil.getInitializedConfiguration();
		new SchemaExport(config).create(true, true);
	}

	public static Session beginTransaction() {
		Session hibernateSession;
		hibernateSession = HibernateUtil.getSession();
		hibernateSession.beginTransaction();
		return hibernateSession;
	}

	public static void commitTransaction() {
		HibernateUtil.getSession().getTransaction().commit();
	}
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618365
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JulTВ двух разных браузерах пользователь открывает сущность
В вебе всё проще пареной репы. Нет ООП и состояния объектов. Все стемятся чтобы ВЕСЬ код отработал за HTTP запрос клиента за 0,0001 сек.
А-ля процедурный подход.
Сделай минимальный тест чтобы 2 запроса были в разных потоках и всё освобождали.
Открыл-закрыл-Открыл-закрыл-Открыл-закрыл-Открыл-закрыл-
))
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618468
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123,

Перечитайте внимательно вопрос из первого сообщения. У топикстартера нет проблемы с тем, чтобы сессию открыть, закрыть, закоммитить, сохранить сущность и т.п. Проблема была в конкурентной модификации одних и тех же данных разными пользователями (в Web-приложении одновременно подсоединённых пользователей может быть очень много).
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618532
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
For AllPetro123,
Перечитайте внимательно вопрос из первого сообщения. У топикстартера нет проблемы с тем, чтобы сессию открыть, закрыть, закоммитить, сохранить сущность и т.п. Проблема была в конкурентной модификации одних и тех же данных разными пользователями (в Web-приложении одновременно подсоединённых пользователей может быть очень много).
может я не вижу?
автор Второй: как правильно реализовывать работу с сессиями Hibernate в веб-приложениях? необходимо открывать-закрывать сессию для каждого действия или как?
...
Рейтинг: 0 / 0
Помогите разобраться с сессиями Hibernate
    #38618546
For All
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123может я не вижу?
автор Второй: как правильно реализовывать работу с сессиями Hibernate в веб-приложениях? необходимо открывать-закрывать сессию для каждого действия или как?Ок, провтыкал, извиняюсь.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Помогите разобраться с сессиями Hibernate
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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