LONG作为Hibernate映射到MySQL的主键
我想通过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。
显然我没有足够的凭据来回答我自己的问题,所以我想它会保持开放,或者如果有人提供一个空的答案,我会接受它。谢谢。
当您使用saveOrUpdate()
方法休眠触发插入查询,如果该对象的ID是null
和update
如果它是任何其他值。我可以看到代码 Person person = new Person(1,"John","Doe");
将id
设置为1
并调用saveOrUpdate()
方法。我假设没有条目为id 1,因此错误被抛出。
要使其工作,您需要进行以下更改。
变化
id
在那种会Long
从long
(包装类,以便它可以支持空)。编写构造函数
new Person("John","Doe");
并保存该对象。
保留交易数据的<generator class="assigned"/>
不是一个好主意。相反,当你首先尝试时,你应该坚持到native
。
我觉得这是一种更简洁的方法来解决您的初始问题,即使您找到了替代解决方案。
谢谢。您假设在'SaveOrUpdate'之前没有'id' = 1的记录是正确的。我试图根据您的建议将类类型更改为“Long”,但如果将生成器设置为“native”,它将恢复为相同的错误。我没有理解你第二点,你从构造函数中省略了id? 'id'不是自动生成的ID,所以我需要能够将其设置为特定值。 – hgus1294
我的意思是让你的数据库选择ID并且在保存的时候不要硬编码这个ID。选择[这里]选项(http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id)怎样才能做到这一点。 – ManuPK
好的,明白了。在我的实际情况中,'id'是从外部服务提供的,需要持久保存,所以我不能让db决定。如果我只是将类类型更改为“Long”,并且保留一个构造函数,并使用“Long”,则会得到原始异常。这是否如预期的那样,还是我误解了别的东西?您提到交易发生器=“分配”风险。有什么风险? – hgus1294
你可以发布你的完整堆栈跟踪,长期和BIGINT应该工作正常,我已经使用它本人没有发现问题,请分享你的stacktrace – mprabhat
什么是你的db列类型定义?而你的id属性类型?无论如何,Bigint为列,Long为java属性是好事。 – polypiel
@mprabhat完成。它有一条消息说'我不知道嵌套事务不支持',我以前没有看到。不知道它是什么意思? – hgus1294