Hibernates PostgreSQL-dialekt är inte särskilt ljus. Den känner inte till dina per-SERIAL-sekvenser och antar att det finns en global databasomfattande sekvens som kallas "hibernate_sequence" som den kan använda.
(UPPDATERA :Det verkar som att nyare Hibernate-versioner kan använda standardsekvenserna per tabell när GenerationType.IDENTITY
är specificerad. Testa din version och använd denna istället för nedan om den fungerar för dig.)
Du måste ändra dina mappningar för att explicit specificera varje sekvens. Det är irriterande, repetitivt och meningslöst.
@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
är ganska viktigt. Om du utelämnar det kommer Hibernate blint att anta att sekvensen är definierad med INCREMENT 50
så när den får ett värde från en sekvens kan den använda det värdet och de 49 värdena under det som unika genererade nycklar. Om dina databassekvenser ökar med 1 - standard - kommer detta att resultera i unika överträdelser när Hibernate försöker återanvända befintliga nycklar.
Observera att det kommer att få en nyckel i taget resultera i ytterligare en tur och retur per insats. Såvitt jag kan se kan Hibernate inte använda INSERT ... RETURNING
för att effektivt returnera genererade nycklar, inte heller kan den uppenbarligen använda gränssnittet för JDBC-genererade nycklar. Om du säger åt den att använda en sekvens kommer den att anropa nextval
för att få värdet insert
det uttryckligen, vilket resulterar i två rundresor. För att minska kostnaden för det kan du ställa in en större ökning på nyckelsekvenser med många inserts , kom ihåg att ställa in det på kartläggningen och den underliggande databassekvensen. Det gör att Hibernate anropar nextval
mindre ofta och cacheblock med nycklar att dela ut allt eftersom.
Jag är säker på att du kan se från ovanstående att jag inte håller med om designvalen för Hibernate som gjorts här, åtminstone från perspektivet att använda det med PostgreSQL. De bör använda getGeneratedKeys
eller med INSERT ... RETURNING
med DEFAULT
för nyckeln, låta databasen ta hand om detta utan att Hibernate behöver besvära sig över namnen på sekvenserna eller explicit åtkomst till dem.
BTW, om du använder Hibernate med Pg vill du möjligen också ha en oplock-utlösare för Pg för att låta Hibernates optimistiska låsning interagera säkert med normal databaslåsning. Utan det eller något liknande kommer dina Hibernate-uppdateringar att tendera att smutskasta ändringar som görs via andra vanliga SQL-klienter. Fråga mig hur jag vet.