2011-10-11 8 views
5

Mam kolumnę klucza podstawowego, która jest kolumną INT, którą chciałbym zmienić na BIGINT. Nasze środowisko testowe i produkcyjne wykorzystuje MySQL, ale do testów jednostkowych używamy wbudowanej bazy danych H2.Liquibase: Zmień kolumnę autoinkrecji INT na BIGINT przy użyciu refaktoryzacji modifyDataType z bazą danych H2

Stworzyłem następujące Liquibase refaktoryzacji:

... 
<changeSet id="1" author="trond"> 
    <modifyDataType tableName="event" columnName="id" newDataType="BIGINT" /> 
    <rollback> 
     <modifyDataType tableName="event" columnName="id" newDataType="INT" /> 
    </rollback> 
</changeSet> 
... 

pracach Refaktoryzacja, ale gdy próbuję utrzymywać obiekt do bazy danych przy użyciu Hibernacja, pojawia się następujący komunikat o błędzie (mam owinięty błąd komunikat)

ERROR org.hibernate.util.JDBCExceptionReporter [main]: NULL not allowed for column "ID"; 
    SQL statement: insert into event (id, eventtime, guid, meta, objectguid, originatorid, subtype, type) values (null, ?, ?, ?, ?, ?, ?, '0') [90006-140] 

JDBC exception on Hibernate data access: 
    SQLException for SQL [insert into event (id, eventtime, guid, meta, objectguid, originatorid, subtype, type) values (null, ?, ?, ?, ?, ?, ?, '0')]; 
    SQL state [90006]; error code [90006]; could not insert: [event.MyEvent]; 
    nested exception is org.hibernate.exception.GenericJDBCException: could not insert: [event.MyEvent] 

Klasa MyEvent dziedziczy z AbstractBaseEvent którym określono następujące odwzorowanie hibernacji kodu:

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private long id; 

Kilka punktów:

  • Mapowanie hibernacji działa przed refaktoringu typu danych
  • Wersja Liquibase jest 2.0.1
  • , czy to działa z MySQL nie został jeszcze przetestowany

Odpowiedz

6

testowałem (Hibernate 3.6.2.Final, H2 1.3.160, dialekt: org.hibernate.dialect.H2Dialect), co dzieje się w Twoim przypadku:

  • Kiedy GenerationType jest AUTO i rodzaj danych jest INT, aktualna generacja typu to SEKWENCJA.
  • Gdy GenerationType ma wartość AUTO, a typem danych jest BIGINT, faktycznym rodzajem generacji jest IDENTYFIKACJA. W rezultacie to się nie powiedzie, jeśli pole identyfikatora to zdefiniowane jako WIELKA KLUCZA PODSTAWOWA ID BIGINT, a nie jako ID IDENTYFIKACJA BIGINT (dodanie KLAWISZA PRIMARY tutaj z H2 byłoby zbędne).

Co można zrobić:

Jeśli chcesz rzeczywisty typ pokolenie być sekwencji, tak jak poprzednio, następnie

@GeneratedValue(strategy = GenerationType.SEQUENCE) 

wydaje się działać. Nie trzeba wprowadzać żadnych zmian w samej sekwencji, ponieważ zgodnie z typem documentation jest to BIGINT. Robiłbym tak, ponieważ wtedy nic tak naprawdę się nie zmienia i jest jasne, w jaki sposób generowana jest sekwencja

Inną możliwością jest zdefiniowanie kolumny jako IDENTITY z parametrem startValue (z powodu możliwych istniejących wartości) i użycie GenerationType.AUTO jak poprzednio.

+0

Bardzo dobra analiza - dziękuję. Jedynym problemem jaki widzę przy użyciu SEQUENCE jest to, że MySQL nie obsługuje sekwencji. Jedną z opcji może być użycie tabeli sekwencji, z której korzystaliśmy w innym przypadku. – tronda

+0

Dobry pomysł - używanie stołu jest i tak najbardziej przenośne. –

+0

Jeśli chodzi o przenośność, to zasadniczo nie ma wątpliwości: musisz użyć '@ TableGenerator'. –

1

Chciałbym najpierw zmienić @GenerationType do czegoś konkretnego (jak IDENTITY) tak, by wykluczyć jakiekolwiek problemy z hibernacji coraz dziwne wartości z sekwencji. Lub całkowicie go usunąć.

Twoje refaktoryzacja wygląda dobrze i nie widzę żadnych oczywistych problemów.

H2 i Liquibase często nie grają ładnie, jeśli chodzi o cytowane identyfikatory; Klasa bazy danych H2 w Liquibase cytuje niektóre i nie cytuje innych. Może konwersja skrzypiec cię pieprzy?

EclipseLink czasami ma problemy, gdy prymitywny typ jest 0 (!), Ponieważ czasami potraktuje taką wartość jak null lub niezainicjowany, ale moim Hibernate wiedzy nie cierpi z tego ograniczenia.

To nie jest odpowiedź, wiem, ale mam nadzieję, że powinnaś wskazać ci właściwy kierunek.

Powiązane problemy