Pergunta

Eu estou trabalhando em um aplicativo de banco de dados que é principalmente somente leitura, mas não há uma tabela que registra o movimento do usuário no aplicativo e tem um grande número de gravações para ele. Para cada poucos milhares de gravações, vemos algumas exceções no log de erro assim:

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

A tabela em questão tem o seguinte esquema:

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 o correspondente Hibernate mapeamento XML:

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

É possível, embora improvável, que várias instâncias do nosso webapp poderia estar escrevendo para o banco de dados de uma só vez, já que números que versão em nosso contexto webapp, de forma transparente lançar novas versões dos aplicativos. Os clientes com a versão antiga do aplicativo em cache no seu navegador web seria assim acessar as versões antigas do servidor, que nós undeploy depois de algumas semanas.

De qualquer forma, não estou convencido de que este é o problema, mas eu sou suspeito que há algum problema de sincronização entre MySQL e Hibernate na mão aqui. Iria mudar o meu gerador de seqüência, seqhilo ou hilo ajuda? Além disso, se você pode fornecer um exemplo de criação de um tal gerador no MySQL, que seria muito útil, como a maioria dos recursos on-line são simplesmente copiar-colar a partir dos exemplos lamentavelmente minimalistas no manual Hibernate.

Foi útil?

Solução

Incremento é definitivamente ruim se você tiver mais de um processo de escrita para a mesma mesa - você é obrigado a ter colisões.

Uma vez que é MySQL que estamos falando, a coisa mais fácil de uso seria identity. Em seu mapeamento do Hibernate:

<generator class="identity"/>

No seu 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;

Para alterar uma tabela existente:

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

onde $ NEW_VALUE $ deverá ser substituído pelo próximo ID disponível para que seqüência não redefinir a 1.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top