简体   繁体   中英

LONG as primary key in Hibernate mapping to MySQL

I am trying to implement persistence of some Java objects via Hibernate mapping to a MySQL table. When I commit I get a message saying 'Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1'.

My hypothesis is that the problem is caused from having a long -field in my Java POJO that I want to use as my primary key in the MySQL table. Since I was not able to use datatype LONG as my primary key in MySQL table (ERROR 1170: BLOB/TEXT column 'id' used in key specification without a key length) I concluded from some googling and this post that BIGINT would be the suitable mapping for long . However it is not updating.

My test POJO Person is very simple. It has 3 fields: id (long), firstname (String), lastname (String) with setters and getters, etc.

I do the hibernate mapping in xml (person.hbm.xml) that essentially looks like (minus headings):

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

My actual java code snippet that is supposed to save or update the record is simple:

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

And here's that thing, this all works just fine if I change the type of id to an int (Integer) in the Person object and in the MySQL table. However, I do not have that option for the actual objects that I want to persist so the question is; what am I doing wrong or what should I do to get it to work? Thanks.

ADDING 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

UPDATE: OK, I have finally worked it out. I changed the hibernate generator class from 'native' to 'assigned' and now it works as expected. So now the hibernate mapping looks like:

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

Must admit I did not know the meaning of that parameter (copied from somewhere) and had no idea it could cause this much headache. Found this explanation which was quite useful.

Apparently I do not have enough credentials to answer my own questions so I guess that it will remain open or if someone provides an empty answer, I will accept it. Thanks.

When you use the saveOrUpdate() method hibernate fires the insert query if the id of the object is null and update if it is any other value. I can see the code, Person person = new Person(1,"John","Doe"); setting the id to 1 and calling the saveOrUpdate() method. I am assuming there are no entries for the id 1 and hence the error is thrown.

To make it work, you need to make the below changes.

  1. Change the Type of id in person to Long from long (The wrapper class so that it can support null).

  2. Write the constructor new Person("John","Doe"); and save that object.

It is not a good Idea to keep the <generator class="assigned"/> for the transactional data. Instead you should be sticking to the native as you were trying first.

I feel this is a cleaner way to solve your initial problem, even though you have found an alternate solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM