2009-07-30 14 views
7

Pracuję w aplikacji bazy danych, która jest przeważnie tylko do odczytu, ale jest jedna tabela, która rejestruje ruchy użytkownika w aplikacji i ma dużą liczbę zapisów do niego. Dla każdego kilka tysięcy pisze, widzimy kilka wyjątków w dzienniku błędów tak:Otrzymywanie duplikatów błędów wpisu z Hibernate, czy MySQL jest winien?

[WARN][2009-07-30 11:09:20,083][org.hibernate.util.JDBCExceptionReporter] SQL Error: 1062, SQLState: 23000 
[ERROR][2009-07-30 11:09:20,083][org.hibernate.util.JDBCExceptionReporter] Duplicate entry '17011' for key 1 
[ERROR][2009-07-30 11:09:20,083][org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session 
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) 

tabeli w pytaniu ma następujący schemat:

CREATE TABLE IF NOT EXISTS `my_table` (
    `id` int(11) NOT NULL, 
    `data1` int(11) NOT NULL, 
    `data2` int(11) NOT NULL, 
    `timestamp` datetime default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; 

i odpowiadająca XML mapowania Hibernate:

<hibernate-mapping> 
    <class name="mycorp.MyClass" table="my_table"> 
    <id name="id" column="id" type="java.lang.Integer"> 
     <generator class="increment"/> 
    </id> 
    <property name="data1" column="data1" type="java.lang.Integer"/> 
    <property name="data2" column="data2" type="java.lang.Integer"/> 
    <property name="timestamp" column="timestamp" type="java.util.Date"/> 
    </class> 
</hibernate-mapping> 

Jest możliwe, choć mało prawdopodobne, że wiele wystąpień naszego webappa może być zapisanych do bazy danych na raz, ponieważ numery wersji w naszym kontekście webapp, aby bezproblemowo zwolnić nowy v ersions aplikacji. Klienci ze starszą wersją aplikacji przechowywaną w pamięci podręcznej przeglądarki mieliby dostęp do starych wersji serwera, które wycofaliśmy po kilku tygodniach.

W każdym razie nie jestem przekonany, że to jest problem, ale podejrzewam, że istnieje problem synchronizacji między MySQL i Hibernate tutaj. Czy zmieniłbym generator na sekwencję, seqhilo lub hilo? Ponadto, jeśli możesz podać przykład ustawienia takiego generatora w MySQL, byłoby to bardzo pomocne, ponieważ większość zasobów online jest po prostu skopiowana z przykrych minimalistycznych przykładów w podręczniku Hibernate.

Odpowiedz

9

Przyrost jest zdecydowanie zły, jeśli masz więcej niż jeden zapis procesu do tego samego stołu - z pewnością będziesz mieć kolizje.

Ponieważ MySQL mówimy, najłatwiejsze w użyciu byłoby identity. W swojej mapowania Hibernate:

<generator class="identity"/> 

w skrypcie MySQL:

CREATE TABLE IF NOT EXISTS `my_table` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `data1` int(11) NOT NULL, 
    `data2` int(11) NOT NULL, 
    `timestamp` datetime default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; 

Aby zmienić istniejącą tabelę:

ALTER TABLE `my_table` 
    CHANGE COLUMN `id` `id` int(11) NOT NULL AUTO_INCREMENT=$NEW_VALUE$; 

gdzie $ NEW_VALUE $ powinien zostać zastąpiony przez kolejnego dostępnego id tak że sekwencja nie resetuje do 1.

+0

bardzo dokładny i jasnej odpowiedzi - dzięki! –

Powiązane problemy