2011-12-01 63 views
5

我想通过Hibernate映射到MySQL表来实现一些Java对象的持久性。当我提交时,我收到一条消息,说'批量更新返回来自update [0]的意外行计数;实际行数:0;预计:1'。LONG作为Hibernate映射到MySQL的主键

我的假设是,这个问题是由我在我的Java POJO中有一个long字段引起的,我想用它作为MySQL表中的主键。由于我无法在MySQL表中使用数据类型LONG作为我的主键(错误1170:密钥规范中使用的BLOB/TEXT列'id',而且没有密钥长度),所以我从一些Google搜索结果和这个post得出结论:BIGINT会是合适的映射为long。但它不会更新。

我的测试POJO Person很简单。它有3个字段:id(long),firstname(String),lastname(String)与setter和getters等。

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

我实际的Java代码片断:

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

及这里的东西,这一点,如果我改变的类型的所有作品就好id添加到Person对象和MySQL表中的int(整数)。但是,我没有这个选择来解决我想要坚持的实际对象,所以问题在于;我做错了什么,或者我该怎么做才能使它工作?谢谢。

ADDING堆栈跟踪:

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,我终于工作了。我将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> 

必须承认,我不知道该参数(从某处复制)的含义,也不知道它可能会导致此大为头痛。发现这是非常有用的explanation

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

+0

你可以发布你的完整堆栈跟踪,长期和BIGINT应该工作正常,我已经使用它本人没有发现问题,请分享你的stacktrace – mprabhat

+0

什么是你的db列类型定义?而你的id属性类型?无论如何,Bigint为列,Long为java属性是好事。 – polypiel

+0

@mprabhat完成。它有一条消息说'我不知道嵌套事务不支持',我以前没有看到。不知道它是什么意思? – hgus1294

回答

5

当您使用saveOrUpdate()方法休眠触发插入查询,如果该对象的ID是nullupdate如果它是任何其他值。我可以看到代码 Person person = new Person(1,"John","Doe");id设置为1并调用saveOrUpdate()方法。我假设没有条目为id 1,因此错误被抛出。

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

  1. 变化id在那种会Longlong(包装类,以便它可以支持空)。

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

保留交易数据的<generator class="assigned"/>不是一个好主意。相反,当你首先尝试时,你应该坚持到native

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

+0

谢谢。您假设在'SaveOrUpdate'之前没有'id' = 1的记录是正确的。我试图根据您的建议将类类型更改为“Long”,但如果将生成器设置为“native”,它将恢复为相同的错误。我没有理解你第二点,你从构造函数中省略了id? 'id'不是自动生成的ID,所以我需要能够将其设置为特定值。 – hgus1294

+0

我的意思是让你的数据库选择ID并且在保存的时候不要硬编码这个ID。选择[这里]选项(http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id)怎样才能做到这一点。 – ManuPK

+0

好的,明白了。在我的实际情况中,'id'是从外部服务提供的,需要持久保存,所以我不能让db决定。如果我只是将类类型更改为“Long”,并且保留一个构造函数,并使用“Long”,则会得到原始异常。这是否如预期的那样,还是我误解了别的东西?您提到交易发生器=“分配”风险。有什么风险? – hgus1294