PostgreSQL диалектът на Hibernate не е много ярък. Той не знае за вашите per-SERIAL последователности и предполага, че има глобална последователност за цялата база данни, наречена „hibernate_sequence“, която може да използва.
(АКТУАЛИЗИРАНЕ :Изглежда, че по-новите версии на Hibernate може да използват последователностите по подразбиране за таблица, когато GenerationType.IDENTITY
е уточнено. Тествайте версията си и използвайте тази вместо по-долу, ако работи за вас.)
Трябва да промените своите съпоставяния, за да посочите изрично всяка последователност. Това е досадно, повтарящо се и безсмислено.
@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {
private static final long serialVersionUID = -7049957706738879274L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="judgements_id_seq")
@SequenceGenerator(name="judgements_id_seq", sequenceName="judgements_id_seq", allocationSize=1)
@Column(name = "JUD_ID")
private Long _judId;
...
allocationSize=1
е доста важно. Ако го пропуснете, Hibernate сляпо ще приеме, че последователността е дефинирана с INCREMENT 50
така че когато получи стойност от последователност, може да използва тази стойност и 49-те стойности под нея като уникално генерирани ключове. Ако последователностите на вашата база данни се увеличат с 1 – по подразбиране – това ще доведе до уникални нарушения, тъй като Hibernate се опитва да използва повторно съществуващите ключове.
Имайте предвид, че получаването на един ключ наведнъж ще води до допълнително двупосочно пътуване на вложка. Доколкото мога да кажа, Hibernate не може да използва INSERT ... RETURNING
за ефективно връщане на генерирани ключове, нито очевидно може да използва интерфейса на генерираните ключове на JDBC. Ако му кажете да използва последователност, той ще извика nextval
за да получите стойността, след това insert
това изрично, което води до две двупосочни пътувания. За да намалите цената на това, можете да зададете по-голямо увеличение на ключовите последователности с много вмъквания , като не забравяте да го зададете на картографирането и основната последователност на базата данни. Това ще накара Hibernate да извика nextval
по-рядко и кеширайте блокове с ключове, които да раздавате, докато върви.
Сигурен съм, че можете да видите от горното, че не съм съгласен с направените тук избори за дизайн на Hibernate, поне от гледна точка на използването му с PostgreSQL. Те трябва да използват getGeneratedKeys
или с помощта на INSERT ... RETURNING
с DEFAULT
за ключа, оставяйки базата данни да се погрижи за това, без да се налага Hibernate да се затруднява с имената на последователностите или изричен достъп до тях.
BTW, ако използвате Hibernate с Pg, вероятно ще искате и задействане на oplock за Pg, за да позволите на оптимистичното заключване на Hibernate да взаимодейства безопасно с нормалното заключване на базата данни. Без него или нещо подобно, вашите актуализации на Hibernate ще са склонни да разрушат промените, направени чрез други обикновени SQL клиенти. Попитайте ме откъде знам.