LONG作为Hibernate映射到MySQL的主键

hgu*_*294 5 java mysql hibernate

我试图通过Hibernate映射到MySQL表来实现一些Java对象的持久性.当我提交时,我收到一条消息,说"批量更新从更新[0]返回了意外的行数; 实际行数:0; 预期:1'.

我的假设是问题是由于long我的Java POJO中有一个字段,我想用它作为MySQL表中的主键.由于我无法使用数据类型LONG作为我在MySQL表中的主键(ERROR 1170:BLOB/TEXT列'id'在密钥规范中使用而没有密钥长度)我从一些谷歌搜索和这篇帖子得出结论,BIGINT将是合适的映射long.但它没有更新.

我的测试POJO Person非常简单.它有3个字段:id(long),firstname(String),lastname(String),带有setter和getter等.

我在xml(person.hbm.xml)中执行基本上看起来像(减去标题)的hibernate映射:

<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>
Run Code Online (Sandbox Code Playgroud)

我应该保存或更新记录的实际java代码片段很简单:

Transaction tr = session.beginTransaction();            
Person person = new Person(1,"John","Doe");
session.saveOrUpdate(person);
tr.commit();
Run Code Online (Sandbox Code Playgroud)

这就是,如果我id在Person对象和MySQL表中将类型更改为int(Integer),这一切都可以正常工作.但是,对于我想要保留的实际对象,我没有那个选项,所以问题是; 我做错了什么或者我该怎么办才能让它发挥作用?谢谢.

添加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
Run Code Online (Sandbox Code Playgroud)

更新:好的,我终于解决了.我将hibernate生成器类从"native"更改为"assigned",现在它按预期工作.所以现在hibernate映射看起来像:

<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>
Run Code Online (Sandbox Code Playgroud)

必须承认我不知道该参数的含义(从某处复制)并且不知道它可能会引起这么多头痛.找到这个非常有用的解释.

显然我没有足够的凭据来回答我自己的问题,所以我猜它会保持开放,或者如果有人提供空答案,我会接受它.谢谢.

Man*_*uPK 5

当您使用该saveOrUpdate()方法时,如果对象的id是null,update并且它是任何其他值,则hibernate将触发插入查询.我可以看到代码, Person person = new Person(1,"John","Doe");设置id1和调用saveOrUpdate()方法.我假设没有id 1的条目,因此抛出错误.

要使其工作,您需要进行以下更改.

  1. 改变的类型id亲自Longlong(包装类,以便它可以支持空).

  2. 编写构造函数new Person("John","Doe");并保存该对象.

保留<generator class="assigned"/>交易数据并不是一个好主意.相反,你应该坚持native你先尝试的方式.

我觉得这是解决初始问题的一种更简洁的方法,即使您已经找到了替代解决方案.