Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Hibernate & GenerationType.IDENTITY


Автор: _sten_ 19.2.2010, 20:56
Есть ентити класс и замаплен:
Код

@Entity
@Table(name = "item")
public class Item {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

        // getters and setters here

}


для генирации ид используется GenerationType.IDENTITY стратегия которая оначает что ид будет пропущен в инесерте(будет сгенерирован БД через значение по умолчанию)

вот DDL для таблички(PostgreSQL):
Код

create sequence item_id_seq;
CREATE TABLE item  ( 
    id int4 NOT NULL DEFAULT nextval('item_id_seq'),
    name varchar(255),
    PRIMARY KEY(id)
);


сохраняем ентити с помощью хибернета:
Код

        Item item = new Item();
        item.setName("test");
        Session session = sessionFactory.openSession();
        session.save(item);
        System.out.println("id: " + item.getId());

вот все что пишет хибернет:
Код

    insert 
    into
        item
        (name) 
    values
        (?)

(без ид)

не понятно как хибернет узнает ид в последней строке... ведь ид было сгенерено базой(через сиквесн) без использования хибернета, и хибернет ни писал никаких селектов бля определения ид...

Автор: MaxPayneC 19.2.2010, 21:25
Интересный вопрос. Возможно, прозвучит глупо, но все же спрошу - System.out.println("id: " + item.getId()); действительно выводит id созданной записи? Если да, тогда посмотрите консоль, не было ли селекта.

Автор: _sten_ 19.2.2010, 22:02
да, действительно System.out.println("id: " + item.getId()); выводит ид.
из доки по Session интерфейсу:
Цитата

    Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned  generator is used.) This operation cascades to associated instances if the association is mapped with cascade="save-update".

    Parameters:
        object - a transient instance of a persistent class 
    Returns:
        the generated identifier 
    Throws:
        HibernateException


тоесть можно сделать и так:
Код

Long id = (Long) session.save(item);
System.out.println("id: " + id);


все что есть на консоли указано выше.

Автор: MaxPayneC 19.2.2010, 23:01
Все, что мне удалось найти на этот счет - это
Цитата

You can retrieve the most recent AUTO_INCREMENT value with the LAST_INSERT_ID() SQL function or the mysql_insert_id() C API function. These functions are connection-specific, so their return values are not affected by another connection which is also performing inserts.

Видимо hibernate вызывает эти функции.

Автор: jk1 19.2.2010, 23:03
Может быть, дело в этом:
Цитата

For identifier generators that store values in the database, it is inefficient for them to hit the database on each and every call to generate a new identifier value. Instead, you can group a bunch of them in memory and only hit the database when you have exhausted your in-memory value group. This is the role of the pluggable optimizers. 
1) hilo: applies a hi/lo algorithm around the database retrieved values. The values from the database for this optimizer are expected to be sequential. The values retrieved from the database structure for this optimizer indicates the "group number". The increment_size is multiplied by that value in memory to define a group "hi value".
2) pooled: as with the case of hilo, this optimizer attempts to minimize the number of hits to the database. Here, however, we simply store the starting value for the "next group" into the database structure rather than a sequential value in combination with an in-memory grouping algorithm. Here, increment_size refers to the values coming from the database.

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id-enhanced

Автор: _sten_ 19.2.2010, 23:06
продебажил выяснил что хибернет пишет:
Код

insert into item (name) values ('test') RETURNING * 


типа инсерт и селект вместе)))
терь все стало на свои места

осталось только выяснить входит ли этот RETURNING в стандарт SQL или это чисто фишка Postgre

Автор: MaxPayneC 19.2.2010, 23:07
Цитата
Может быть, дело в этом:

Маловероятно, я три раза запускал тест, а перед третьим запуском поменял авто_инкремент на 100.

Автор: _sten_ 19.2.2010, 23:10
кто то что знает об этом RETURNING? что то не могу ничего нагуглить...

Добавлено через 8 минут и 22 секунды
вот нашел:
Цитата

INSERT conforms to the SQL standard, except that the RETURNING clause is a PostgreSQL extension. Also, the case in which a column name list is omitted, but not all the columns are filled from the VALUES clause or query, is disallowed by the standard. 

значит RETURNING - это фишка чисто постгри

интересно как хибернет решает эту проблему с другими СУБД

Автор: MaxPayneC 19.2.2010, 23:23
Цитата(_sten_ @  19.2.2010,  23:10 Найти цитируемый пост)

интересно как хибернет решает эту проблему с другими СУБД 

Встроенными средствами СУБД. В случае например MySQL - это мой пред-предыдущий пост, в случае Oracle если я не ошибаюсь, тоже RETURNING.

Автор: jk1 19.2.2010, 23:27
Цитата

For versions up to and including 11g Release 1, Oracle doesn't support RETURNING construct.

http://www.oracle-developer.net/display.php?id=413

Экспериментально выяснилось, что как минимум 11.1.0.6.0 эту конструкцию поддерживает

Автор: _sten_ 19.2.2010, 23:29
спасибо, проблема решена

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)