Java 作为Hibernate映射到MySQL的主键

Java 作为Hibernate映射到MySQL的主键,java,mysql,hibernate,Java,Mysql,Hibernate,我试图通过Hibernate映射到MySQL表来实现一些Java对象的持久性。当我提交时,我收到一条消息说“批量更新从更新[0]返回了意外的行数”;实际行数:0;预期:1’ 我的假设是,这个问题是由于在我的Java POJO中有一个long-字段引起的,我想将该字段用作MySQL表中的主键。由于我无法使用datatype LONG作为MySQL表中的主键(错误1170:BLOB/TEXT列“id”在键规范中使用,但没有键长度),我通过一些谷歌搜索得出结论,BIGINT将是LONG的合适映射。但是

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

我的假设是,这个问题是由于在我的Java POJO中有一个
long
-字段引起的,我想将该字段用作MySQL表中的主键。由于我无法使用datatype LONG作为MySQL表中的主键(错误1170:BLOB/TEXT列“id”在键规范中使用,但没有键长度),我通过一些谷歌搜索得出结论,BIGINT将是
LONG
的合适映射。但是,它没有更新

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

我用xml(person.hbm.xml)进行hibernate映射,基本上看起来像(减去标题):

这就是问题所在,如果我在Person对象和MySQL表中将
id
的类型更改为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
更新: 好的,我终于解决了。我将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>

我必须承认,我不知道这个参数(从某处复制)的含义,也不知道它会引起这么多头痛。我发现这很有用


显然,我没有足够的资格来回答我自己的问题,所以我猜它将保持开放状态,或者如果有人提供了一个空的答案,我将接受它。谢谢。

当您使用
saveOrUpdate()
方法时,如果对象的id为
null
update
如果是任何其他值,hibernate将触发insert查询。
我可以看到代码,
Person-Person=新人(1,“约翰”,“多伊”)
id
设置为
1
并调用
saveOrUpdate()
方法。我假设没有id 1的条目,因此会抛出错误

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

  • id
    的个人类型从
    Long
    更改为
    Long
    (包装器类可以支持null)

  • 编写构造器
    新人(“John”,“Doe”)并保存该对象

  • 为事务数据保留
    不是一个好主意。相反,您应该在第一次尝试时坚持使用
    本机


    我觉得这是一种更干净的方法来解决您最初的问题,即使您已经找到了另一种解决方案。

    您能发布完整的stacktrace吗,long和BIGINT应该可以,我个人使用过它没有发现问题,请分享您的stacktrace您的db列类型定义是什么?您的id属性类型是什么?无论如何,列的Bigint和java的Long属性都是正确的。@mprabhat Done。它有一条消息说“嵌套事务不受支持”,这是我以前没有看到的。不知道这是什么意思吗?@polypiel抱歉,我不确定我是否理解这个问题。MySQL中的数据类型是BIGINT(20),hibernate配置就是我上面发布的所有配置。我意识到“嵌套事务不受支持”可能是另一个单独的异常,因为我试图在前一个事务失败时启动新事务。因此,这与本文无关。谢谢。您的假设是正确的,即在
    SaveOrUpdate
    之前没有
    id
    =1的以前记录。根据您的建议,我试图将类类型更改为
    Long
    ,但如果我将生成器设置为
    native
    ,则会返回相同的错误。我不明白你的第二点,你在构造函数中省略了
    id
    id
    不是自动生成的id,因此我需要能够将其设置为特定值。我的意思是让数据库选择id,并且在保存时不要硬编码id。从选项中选择如何做。好的,知道了。在我的实际场景中,
    id
    是由一个外部服务提供的,因此需要保持不变,因此我不能让db决定。如果我只是将类类型更改为
    Long
    ,并保留一个采用
    Long
    的构造函数,我会得到原始异常。这是意料之中的还是我误解了什么?您提到了generator=
    为交易分配的风险。风险是什么?
    
    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>