Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Помогите разобраться с сессиями Hibernate / 23 сообщений из 23, страница 1 из 1
16.04.2014, 16:08
    #38616654
JulT
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
Есть фабрика по созданию сессии:
Код: 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
16.04.2014, 16:23
    #38616679
For All
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
Не надо делать addOrUpdate. Надо делать только Update. И тогда хибернейт заругается, что сущности уже нет (удалена) и не сохранит её снова. Ексепшн из хиберейта поймать и показать юзеру в браузере в виде вменяемого сообщения (окошко там всплывающее и т.д.)
...
Рейтинг: 0 / 0
17.04.2014, 00:48
    #38617079
JulT
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
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
17.04.2014, 10:34
    #38617238
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
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
17.04.2014, 12:15
    #38617365
For All
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
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
17.04.2014, 12:31
    #38617385
Сергей Арсеньев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
IMHO, надо с начала расписаьб бизнес-логику и утвердить ее, а потом делать согласно ей.

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

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

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

И с Hibernate будет разобраться намного легче.
Вся эта логика уже реализована хибернейтом и писать её самому заново совершенно нет необходимости.
...
Рейтинг: 0 / 0
17.04.2014, 15:18
    #38617647
JulT
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
Всем огромное спасибо за советы.
Я вот еще чего не могу понять. Вот код одного из моих методов:
Код: 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
17.04.2014, 15:41
    #38617676
Сергей Арсеньев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
For AllВся эта логика уже реализована хибернейтом
Я рад, что Hibernate думает за Вас, но написать на бумаге, что именно надо делать в случаях, которые отмечены ... , все равно не помешает.
...
Рейтинг: 0 / 0
17.04.2014, 15:46
    #38617685
Сергей Арсеньев
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
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
17.04.2014, 16:03
    #38617703
JulT
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
Сергей Арсеньев,
нет, нужно было так сразу написать:
Session sess=currentSession();
sess.beginTransaction();

sess.save(liga);

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

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

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

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

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

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

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

JulTСпасибо всем за ответы.
Я использую thread контекст: <property name="current_session_context_class">thread</property>
это значит что вы не выходя из потока должны получить сессию хибера (а не БД), использовать и закрыть.
Если это сервлет, то за доли секунды пока идёт вызов сервлета. Т.к. он может быть в потоке.
15894711
В десктопе всё по другому.
...
Рейтинг: 0 / 0
18.04.2014, 01:59
    #38618199
JulT
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
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
18.04.2014, 09:54
    #38618340
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
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
18.04.2014, 09:56
    #38618349
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
Код: 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
18.04.2014, 10:06
    #38618365
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
JulTВ двух разных браузерах пользователь открывает сущность
В вебе всё проще пареной репы. Нет ООП и состояния объектов. Все стемятся чтобы ВЕСЬ код отработал за HTTP запрос клиента за 0,0001 сек.
А-ля процедурный подход.
Сделай минимальный тест чтобы 2 запроса были в разных потоках и всё освобождали.
Открыл-закрыл-Открыл-закрыл-Открыл-закрыл-Открыл-закрыл-
))
...
Рейтинг: 0 / 0
18.04.2014, 11:17
    #38618468
For All
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите разобраться с сессиями Hibernate
Petro123,

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


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