hibernate 2.0 и @@identity в MSSQL
От: dimpon  
Дата: 01.12.03 12:17
Оценка:
Была проблема — замапить два класса (родитель и наследник) на две таблицы в базе (MSSQL), связанные по id.
В первой таблице (предназначенной для родителя) id поле было indentity.
Проще говоря_ hibrnaty при вставке строки (создании нового объекта) надо было вставить строку в первую таблицуб потом select @@identity вытащить сгенерированный базой ключ и вставить во вторую таблицу запись с этим ключем.
НО был очень удивлен, когда вместо сгенерированного зачения ключа вернулся 0.
Дальнейшее расследование JDBC показало, что select @@identity не вернет ключ сгенерированный при педыдущем Inserte если не закрыть Statement этого inserta. То есть надо делать так:

Statement st = conn.createStatement();
st.executeUpdate("insert into tab(name) values ('ABCDEF')");
st.close();


Statement sta = conn.createStatement();
ResultSet rs = sta.executeQuery("select @@identity");



копание в исходниках hibernate показало, что Statement не всегда закрывается, часто он возвращается в кеш, пришлось "довести напильником" — в классе net.sf.hibernate.persister.NormalizedEntityPersister в методе
Serializable insert(Object[] fields, Object object, SessionImplementor session)
добавить закрытие Statement (statement.close(). После этого все заработало, как и полагается. Согласно документации

Вопрос — кто сталкивался с подобной проблемой, может есть другой метод, или я что-то прогдядел в настройках ?
Метод "русского программиста" конечно работает, но все-таки остается чувство беспокойства...
Re: hibernate 2.0 и @@identity в MSSQL
От: Mishka Норвегия  
Дата: 01.12.03 13:39
Оценка:
Здравствуйте, dimpon:

Странно, у меня всё работат. Правда я тут последними бетами балуюсь, может в этом дело
Re[2]: hibernate 2.0 и @@identity в MSSQL
От: dimpon  
Дата: 01.12.03 14:26
Оценка:
M>Здравствуйте, dimpon:

M>Странно, у меня всё работат. Правда я тут последними бетами балуюсь, может в этом дело


Добрый день !
с hibernate нормально ?

не сочтите за труд попробуйте — такой код будет возвращать identity ? (первый Statement не закрывается)

Statement st = conn.createStatement();
st.executeUpdate("insert into tab(name) values ('ABCDEF')");
//st.close();

Statement sta = conn.createStatement();
ResultSet rs = sta.executeQuery("select @@identity");

while (rs.next()){
         System.out.println("identity= "+rs.getInt(1));
}


у меня identity возвращался только когда

1. insert и select выполняются одной командой
ResultSet rs = sta.executeQuery("insert into tab(name) values ('ABCDEF');select @@identity;");


2. выполняются в одном Statement'е
Statement st = conn.createStatement();
st.executeUpdate("insert into tab(name) values ('ABCDEF')");
ResultSet rs = st.executeQuery("select @@identity");



3. Когда первый Statement закрывается, а потом создаетсЯ новый.

Да, забыл написать — MSSQL 2000 — может это важно.
Re[3]: hibernate 2.0 и @@identity в MSSQL
От: Blazkowicz Россия  
Дата: 01.12.03 14:39
Оценка:
Здравствуйте, dimpon, Вы писали:

D>не сочтите за труд попробуйте — такой код будет возвращать identity ? (первый Statement не закрывается)


D>
D>Statement st = conn.createStatement();
D>st.executeUpdate("insert into tab(name) values ('ABCDEF')");
D>//st.close();

D>Statement sta = conn.createStatement();
D>ResultSet rs = sta.executeQuery("select @@identity");

D>while (rs.next()){
D>         System.out.println("identity= "+rs.getInt(1));
D>}
D>


Может реально изменения в базе ещё не закоммитились? И поэтому такой @@identity? Судя по описанному поведению очень на то похоже.
Re[3]: hibernate 2.0 и @@identity в MSSQL
От: Mishka Норвегия  
Дата: 01.12.03 14:41
Оценка:
Здравствуйте, dimpon:

А причём здесь Hibernate? Или ты получаешь соединение из Session и потом используешь?
Re[4]: hibernate 2.0 и @@identity в MSSQL
От: dimpon  
Дата: 01.12.03 14:51
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, dimpon, Вы писали:


D>>не сочтите за труд попробуйте — такой код будет возвращать identity ? (первый Statement не закрывается)


D>>
D>>Statement st = conn.createStatement();
D>>st.executeUpdate("insert into tab(name) values ('ABCDEF')");
D>>//st.close();

D>>Statement sta = conn.createStatement();
D>>ResultSet rs = sta.executeQuery("select @@identity");

D>>while (rs.next()){
D>>         System.out.println("identity= "+rs.getInt(1));
D>>}
D>>


B>Может реально изменения в базе ещё не закоммитились? И поэтому такой @@identity? Судя по описанному поведению очень на то похоже.


Нет, такой код тоже не работает, дело не в коммите


  Statement st = conn.createStatement();
  st.executeUpdate("insert into tab(name) values ('ABCDEF')");
  conn.commit();
            //st.close();
  Statement sta = conn.createStatement();
  ResultSet rs = sta.executeQuery("select @@identity");
Re[3]: hibernate 2.0 и @@identity в MSSQL
От: Mishka Норвегия  
Дата: 01.12.03 14:54
Оценка:
Здравствуйте, dimpon,

Проверил:

Session hs = ...
Connection con = hs.connection();
Statement st = con.createStatement();
st.executeUpdate("insert into tab(name) values ('ABCDEF')");
//st.close();

Statement sta = con.createStatement();
ResultSet rs = sta.executeQuery("select @@identity");

while (rs.next())
{
  System.out.println("identity= " + rs.getInt(1));
}

Выдаёт "identity= 1".

Никаких доп. функций в hibernate.cfg.xml не стоит, только самое основное.
Re[4]: hibernate 2.0 и @@identity в MSSQL
От: dimpon  
Дата: 01.12.03 14:54
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, dimpon:


M>А причём здесь Hibernate? Или ты получаешь соединение из Session и потом используешь?


нет, это был просто тестовый пример читстый JDBC + MSSQL

Дело в том, что в hibernate как раз используется два Statement'а, причем, второй не закрывается, а возвращается в кеш. (происходит это как раз в классе, net.sf.hibernate.persister.NormalizedEntityPersister )

и только после принудительного закрытия первого Statement все заработало.
Re[4]: hibernate 2.0 и @@identity в MSSQL
От: dimpon  
Дата: 01.12.03 14:56
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, dimpon,


M>Проверил:


M>
M>Session hs = ...
M>Connection con = hs.connection();
M>Statement st = con.createStatement();
M>st.executeUpdate("insert into tab(name) values ('ABCDEF')");
M>//st.close();

M>Statement sta = con.createStatement();
M>ResultSet rs = sta.executeQuery("select @@identity");

M>while (rs.next())
M>{
M>  System.out.println("identity= " + rs.getInt(1));
M>}
M>

M>Выдаёт "identity= 1".

M>Никаких доп. функций в hibernate.cfg.xml не стоит, только самое основное.


хм, может дело в настройках MSSQL...
Re[5]: hibernate 2.0 и @@identity в MSSQL
От: Mishka Норвегия  
Дата: 01.12.03 15:20
Оценка:
Здравствуйте, dimpon, Вы писали:

D>хм, может дело в настройках MSSQL...


Попробуй установить autocommit в false.
Re[6]: hibernate 2.0 и @@identity в MSSQL
От: dimpon  
Дата: 01.12.03 15:24
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, dimpon, Вы писали:


D>>хм, может дело в настройках MSSQL...


M>Попробуй установить autocommit в false.


Вот уж тогда точно придется первый Statement закрывать.
Потому что MSSQL иначе ругается —
Can't start a cloned connection while in manual transaction mode
Re[7]: hibernate 2.0 и @@identity в MSSQL
От: Mishka Норвегия  
Дата: 01.12.03 15:30
Оценка:
Здравствуйте, dimpon, Вы писали:

D>Вот уж тогда точно придется первый Statement закрывать.

D>Потому что MSSQL иначе ругается —
D>Can't start a cloned connection while in manual transaction mode

Это сообщение скорее всего выскакивает из-за того, что selectMethod не установлен в cursor. Посмотри как прописано соединение.
Re[8]: hibernate 2.0 и @@identity в MSSQL
От: dimpon  
Дата: 01.12.03 16:11
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, dimpon, Вы писали:


D>>Вот уж тогда точно придется первый Statement закрывать.

D>>Потому что MSSQL иначе ругается —
D>>Can't start a cloned connection while in manual transaction mode

M>Это сообщение скорее всего выскакивает из-за того, что selectMethod не установлен в cursor. Посмотри как прописано соединение.



О! золотые слова ! все дело было в SelectMethod=cursor и hibernate пачить не надо !

Спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.