Domanda

Sto lavorando a un'applicazione di database che è per lo più di sola lettura, ma esiste una tabella che registra il movimento dell'utente nell'app e ha un gran numero di scritture su di essa. Per alcune migliaia di scritture, nel registro degli errori vengono visualizzate alcune eccezioni:

[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)

La tabella in questione ha il seguente schema:

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;

E il corrispondente XML di mapping 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>

È possibile, sebbene improbabile, che più istanze della nostra webapp possano scrivere contemporaneamente nel database, poiché abbiamo numeri di versione nel nostro contesto webapp per rilasciare senza problemi nuove versioni delle applicazioni. I client con la vecchia versione dell'applicazione memorizzata nella cache nel proprio browser Web accederanno quindi alle vecchie versioni del server, che disimpegneremo dopo alcune settimane.

Ad ogni modo, non sono convinto che questo sia il problema, ma sono sospetto che ci sia qualche problema di sincronizzazione tra MySQL e Hibernate a portata di mano qui. Cambiare il mio generatore in sequenza, seqhilo o hilo sarebbe di aiuto? Inoltre, se puoi fornire un esempio di installazione di un tale generatore in MySQL, ciò sarebbe molto utile, poiché la maggior parte delle risorse online sono semplicemente incollate dagli esempi terribilmente minimalisti nel manuale di Hibernate.

È stato utile?

Soluzione

L'incremento è decisamente negativo se hai più di un processo che scrive sulla stessa tabella: sei tenuto ad avere delle collisioni.

Dato che è MySQL di cui stiamo parlando, la cosa più semplice da usare sarebbe identità . Nella tua mappatura di Hibernate:

<generator class="identity"/>

Nel tuo script 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;

Per modificare una tabella esistente:

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

dove $ NEW_VALUE $ deve essere sostituito dal prossimo ID disponibile in modo che la sequenza non venga reimpostata su 1.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top