LONG как первичный ключ в отображении Hibernate на MySQL - PullRequest
5 голосов
/ 01 декабря 2011

Я пытаюсь реализовать постоянство некоторых объектов Java с помощью преобразования Hibernate в таблицу MySQL.Когда я фиксирую, я получаю сообщение «Пакетное обновление вернуло неожиданное количество строк из-за обновления [0];фактическое количество строк: 0;Ожидается: 1 '.

Моя гипотеза состоит в том, что проблема вызвана наличием поля long в моем Java POJO, которое я хочу использовать в качестве своего первичного ключа в таблице MySQL.Так как я не смог использовать тип данных LONG в качестве своего первичного ключа в таблице MySQL (ОШИБКА 1170: идентификатор столбца BLOB / TEXT, использованный в спецификации ключа без длины ключа), я пришел к выводу о некотором поиске в Google, и это post что BIGINT будет подходящим отображением для long.Однако это не обновление.

Мой тест POJO Person очень прост.Он имеет 3 поля: id (long), firstname (String), lastname (String) с установщиками и получателями и т. Д.

Я делаю отображение гибернации в xml (person.hbm.xml), которое по сути выглядит так:(минус заголовки):

<hibernate-mapping>
  <class name="hibernatetest.Person" table="hibernatetest">
   <id name="id" type="long" column="id" >
   <generator class="native"/>
  </id>

  <property name="firstname">
   <column name="firstname" />
  </property>
  <property name="lastname">
  <column name="lastname"/>
  </property>
 </class>
</hibernate-mapping>

Мой настоящий фрагмент кода Java, который должен сохранить или обновить запись, прост:

Transaction tr = session.beginTransaction();            
Person person = new Person(1,"John","Doe");
session.saveOrUpdate(person);
tr.commit();

И вот эта штука, все это прекрасно работаетесли я изменю тип id на int (целое число) в объекте Person и в таблице MySQL.Тем не менее, у меня нет этой опции для реальных объектов, которые я хочу сохранить, поэтому вопрос таков;что я делаю не так или что я должен сделать, чтобы заставить его работать?Спасибо.

ДОБАВЛЕНИЕ Stacktrace:

Hibernate: update hibernatetest set firstname=?, lastname=? where id=?
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81)
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:57)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3006)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:113)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:273)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:265)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1082)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:317)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
    at com.hibernate.test.TestMain.main(TestMain.java:38)
nested transactions not supported

ОБНОВЛЕНИЕ: ОК, я наконец-то решил это.Я изменил класс генератора гибернации с «нативного» на «назначенный», и теперь он работает как положено.Итак, теперь отображение спящего режима выглядит следующим образом:

<hibernate-mapping>
  <class name="hibernatetest.Person" table="hibernatetest">
   <id name="id" type="long" column="id" >
   <generator class="assigned"/>
  </id>

  <property name="firstname">
   <column name="firstname" />
  </property>
  <property name="lastname">
  <column name="lastname"/>
  </property>
 </class>
</hibernate-mapping>

Должен признать, что я не знал значения этого параметра (скопировано откуда-то) и понятия не имел, что это может вызвать такую ​​сильную головную боль.Нашел это объяснение , которое было весьма полезно.

Очевидно, у меня недостаточно учетных данных, чтобы ответить на мои собственные вопросы, поэтому я предполагаю, что оно останется открытым или, если кто-то даст пустой ответ, япринять это.Спасибо.

1 Ответ

5 голосов
/ 01 декабря 2011

Когда вы используете метод saveOrUpdate(), hibernate запускает запрос вставки, если идентификатор объекта null и update, если это любое другое значение. Я вижу код, Person person = new Person(1,"John","Doe"); установка id на 1 и вызов метода saveOrUpdate().Я предполагаю, что нет никаких записей для идентификатора 1 и, следовательно, выдается ошибка.

Чтобы это работало, вам необходимо внести следующие изменения.

  1. ИзменитьТип id лично для Long из long (класс-обертка, так что он может поддерживать нуль).

  2. Написать конструктор new Person("John","Doe"); и сохранить этот объект.

Не очень хорошая идея хранить <generator class="assigned"/> для транзакционных данных.Вместо этого вам следует придерживаться native, как вы пытались вначале.

Я чувствую, что это более чистый способ решения вашей первоначальной проблемы, даже если вы нашли альтернативное решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...