2013-04-03 16 views
5

Używam powyższy kod do generowania ID:@SequenceGenerator z allocationSize> 1 generuje zduplikowane klucze podstawowe

@Id 
@GeneratedValue(generator = "seqq") 
@SequenceGenerator(name = "seqq", sequenceName = "seqq", allocationSize = 20, initialValue = 1) 
public long getId() { 
    return id; 
} 

również zaktualizowaną persistence.xml:

<property name="hibernate.id.new_generator_mappings" value="true"/> 

i aktualizowane DDL w bazie:

CREATE SEQUENCE seqq 
    INCREMENT 20 
    MINVALUE 1 
    MAXVALUE 9223372036854775807 
    START 9171 
    CACHE 1; 

Dzięki temu atrybut allocSize = 20 jest taki sam jak wartość increment. Jednak dostaję arbitralne błędy, mówiąc, że zduplikowana wartość klucza narusza wyjątkowe ograniczenie "myobjects_pkey". Często ten błąd występuje po pierwszym zapisaniu wersji próbnej. Wygląda na to, że hibernacja próbuje przetrwać obiekt z tym samym identyfikatorem. Jednak START zapewnia, że ​​wiersz jest wyższy niż jakikolwiek istniejący w identyfikatorze tabeli. Jak wyeliminować duplikat błędu ograniczenia?

Odpowiedz

0

próba określenia strategii, jak poniżej:

@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "seqq") 

0

Spróbuj

/** The identity. */ 
    @Id 
    @Column(name = "id", unique = true, nullable = false) 
    @SequenceGenerator(name = "ID_SEQU_GENERATOR", sequenceName = "DB_SEQ") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQU_GENERATOR") 
    public long getId() { 
     return id; 
    } 

DB_SEQ ten powinien być określony w DB as sequence.

0

Po ustawieniu wartości hibernate.id.new_generator_mappings = true, Hibernate wygeneruje wartości id począwszy od LASTPRODUCEDID-ALLOCATIONSIZE. Doświadczyłem następujące z domyślnego 50 allocationSize:

Przed użyciem nowy generator:

entity.id   SEQ last number 
    48847     48847 
    48848     48848 
    48849     48849 
    48850     48850 

Po użyciu nowego generatora:

entity.id   SEQ last number 
    48801     48851 
    48802     48852 

Więc trzeba zwiększyć sekwencję o wielkości alokacji. Ponieważ klauzula "powiększenie" twojej sekwencji powinna być równa allocSize, oznacza to po prostu zapytanie do następnej sekwencji. Możesz to zrobić za pomocą następującego skryptu:

DECLARE 
    v NUMBER; 
    BEGIN 
    FOR r IN (select sequence_name from user_sequences) LOOP 
     EXECUTE IMMEDIATE 'SELECT '|| r.sequence_name ||' .NEXTVAL FROM DUAL' INTO v; 
    END LOOP; 
    END; 
/
Powiązane problemy