java - LONG 作为 Hibernate 映射到 MySQL 的主键

标签 java mysql hibernate

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

我的假设是问题是由于我的 Java POJO 中有一个 long 字段引起的,我想将其用作 MySQL 表中的主键。由于我无法使用 LONG 数据类型作为 MySQL 表中的主键(错误 1170:在没有键长度的键规范中使用了 BLOB/TEXT 列“id”),我从一些谷歌搜索和这个 post 中得出结论。 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>

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

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

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

添加堆栈跟踪:

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 ”更改为“已分配”,现在它按预期工作。所以现在 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,方法 hibernate 会触发插入查询和 update如果它是任何其他值。 我可以看到代码, Person person = new Person(1,"John","Doe");设置 id1并调用 saveOrUpdate()方法。我假设没有 id 1 的条目,因此会抛出错误。

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

  1. 更改 id 的类型亲自到Long来自 long (包装类,以便它可以支持 null)。

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

保留 <generator class="assigned"/> 不是一个好主意对于交易数据。相反,您应该坚持 native正如您首先尝试的那样。

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

关于java - LONG 作为 Hibernate 映射到 MySQL 的主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8339807/

相关文章:

java - 如何将 Java Access Bridge 与 Java 6 一起使用?

java - 在 Eclipse 中使用原型(prototype)选择创建 Maven 项目时出错

hibernate 多对多配置

java - 父级最后在 JBOSS 上进行 Hibernate Arquillian 测试

java - 使用 jUnit 进行 Spring Hibernate 存储库测试

java - 有没有办法创建一个标签,以便编译器运行时用 java 中的语句替换该标签

java - 如何删除字符串中的 HTML 元素?

php - MySQL 中的更新触发器

c# - 如何使用 VS 在 ASP.NET MVC 中部署/发布两个项目 (Codeplex : AspNet. Identity.MySQL)

php - 为什么这些不能插入多对多关系发挥作用?