2012-02-27 16 views
7

Domyślnym generatorem identyfikatorów dla PostgreSQL w Hibernate jest SequenceGenerator [1]. , np. Hibernacja wykona SELECT nextval('hibernate_sequence'), aby wygenerować identyfikator przed wykonaniem INSERT foo (id, ...) VALUES (123, ...) przy zatwierdzaniu sesji.Dlaczego jest domyślny generator Hibernate dla PostgreSql "SequenceGenerator", a nie "IdentityGenerator"?

Jednak PostgreSql obsługuje kolumny autoincrement id (patrz np. [2]), a domyślnym generatorem dla wszystkich innych baz danych obsługujących autoinkrement jest użycie tej cechy [3], a także wykonanie insertów pomijających wartość id i zapytanie baza danych dla nowego identyfikatora (przed zatwierdzeniem sesji, ale w ramach transakcji sesji).

Widziałem niedawną dyskusję [4] sugerującą, że poprzednia strategia jest ogólnie lepsza ze względu na niedopasowanie wstawiania przed sesją-popełnieniem.

Jeśli SequenceGenerator jest lepszy (jak na [4]), dlaczego nie jest domyślny dla baz danych, które go obsługują (patrz [3])?

Jeśli IdentityGenerator jest lepszy, dlaczego PostgreSql jawnie wybiera SequenceGenerator, gdy Postgres obsługuje ten pierwszy (jak na [2])?

Próbowałem znaleźć historię decyzji o zmianie domyślnej w dialekcie PostgreSQL (patrz [1]), ale nie mogłem znaleźć odpowiedniego zatwierdzenia w GitHub. Podążyłem za kodem z powrotem do repozytorium SVN, ale szlak robi się zimny, gdy w r11563 dodano plik PostgreSQLDialect z nieprzydatnym komunikatem "migracja maven" [5]. Nie mogę dłużej śledzić historii. Czy każdy może znaleźć zatwierdzenie, które dodało to zastąpienie? Być może w wiadomości o zatwierdzeniu jest więcej informacji.

Z góry dziękuję.

[1] https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java#L267

[2] PostgreSQL Autoincrement

[3] https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java#L639

[4] http://nhforge.org/blogs/nhibernate/archive/2009/03/20/nhibernate-poid-generators-revealed.aspx

[5] https://source.jboss.org/browse/Hibernate/core/trunk/core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java?focusedRev=14993&fromRev=11563&toRev=14993#r14993

+3

Zakładam, że dzieje się tak dlatego, że typ danych "serial" jest po prostu "sekwencją w przebraniu". –

+0

To nie wyjaśnia tego - wszystkie kolumny autoinkrementacji są sekwencjami w przebraniu. – Rich

+0

nie, nie dla SQL Server lub MySQL, gdzie nie można uzyskać następnej wartości bez wykonywania tej wstawki (co jest dużą różnicą między rozwiązaniem opartym na sekwencji a "automatycznym inkrementowaniem"). –

Odpowiedz

2

Może dlatego, że generatory afterInsert są generalnie zepsute dla PG w NHibernate, ponieważ używają stylu out-parameter OracleStyle, który nie jest obsługiwany przez sterownik npgsql-ADONET, który zwraca wynik jako wynik zapytania, a nie parametr out.

SQL: INSERT INTO .... powrót id do parametru nout; : nhoutparameter = null;

użyciu Oracle działa

command.Execute(); 
object id = command.Parameter["nhoutparameter"].Value; 
Assert.NotNull(id); 

w PG nie. Powinno być

object id = command.ExecuteScalar(); 
+0

Ma to sens w przypadku NHibernate. Czy wiesz, czy to samo dotyczy Hibernate? – Rich

+0

może. Nie mam tu środowiska do testowania. Dla NH właśnie dostałem źródło i uruchomiłem UnitTests przeciwko PG. Wszystkie testy PostInsertGenerator nie powiodły się. Możesz zrobić to samo z Hibernatesource z github działającym na PG. – Firo

0

to tylko spekulacje od I Nie mogę znaleźć dobrej funkcji/wersji dokumentów na postgres, ale ...

Być może dialekt postgresowy został dodany przed wdrożeniem seryjnego, stabilnego, powszechnie używanego lub twórcy, którzy wdrożyli ten dialekt, byli tego świadomi. Zmiana domyślnego generatora identyfikatora dla dialektu byłaby zmianą zerwania, a te są złe.