1

我正在使用 Spring Roo 开发一个 Spring Web 应用程序,仅用于生成持久层类(Web 应用程序本身正在使用 ZK 框架开发),使用 Roo 活动记录模式。

我有一个简单的问题是从数据库中检索实体(特别是从持久类User中,相应的表被命名my_user),让字段在 UI 中编辑,然后将修改后的实体保存在数据库中。

如果我做对了,在我的控制器类中,我有(A)检索具有username可用用户数据的方法:这是通过调用

User user = User.findUsersByUsernameEquals(username).getSingleResult()

并且似乎工作正常(数据正确显示在 UI 上)和(B)将实体数据保存回数据库。为此,我称之为方法

user.merge()

问题是调用时merge()会产生以下异常,因此修改后的数据不会保存在数据库中。

org.hibernate.exception.ConstraintViolationException: could not execute statement; nested exception is javax.persistence.PersistenceException:        
org.hibernate.exception.ConstraintViolationException: could not execute statement[SQL: 1062, 23000]
...
caused by:
...
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
Duplicate entry '<username value>' for key '...'

笔记:

1)User实体作为自动生成的 Id 键。该username字段(不是键)--unique在使用 Roo 生成时标记为。如果我尝试重新生成架构以消除对 的唯一要求username,则合并的效果是在数据库上创建第二条记录(不给出任何例外),具有相同的用户名和不同的 Id 值(这显然不是我想要的行为应用)。

2)查看日志,hibernate(在JPA下使用的持久性提供程序)实际上尝试执行一条sqlINSERT语句(我曾期望过UPDATE):

[DEBUG] (org.hibernate.SQL:104) insert into my_user (address, email, enabled, firstname, password, surname, telephone, username, version) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into my_user (address, email, enabled, firstname, password, surname, telephone, username, version) values (?, ?, ?, ?, ?, ?, ?, ?, ?)

3)如果我调用user.persist()而不是user.merge()我得到与以前相同的异常(这只是一次尝试,如果我理解正确,调用 .persist() 不应该是保存修改实体的正确方法)。

我刚刚开始 JPA 和 Roo 编程,所以我不确定我是否以正确的方式做事。我的印象是这个问题可能与我使用 findUsersByUsernameEquals 和 merge() 读取数据之间的实体分离有关,但这只是一个假设。

提前致谢,

4

1 回答 1

1

我想我已经找到了解决方案,这要归功于这个线程:JPA Hibernate 合并执行插入而不是更新

问题是由于 Rooversion在创建 jpa 实体时自动添加了一个字段。我在我的初始数据库中填充了一组INSERT INTO我没有为此字段设置值的位置,导致它被初始化为 null。

如果我在我的INSERT INTO语句中将其设置为 0,则代码有效。(在使用 直接从 java 代码创建实例时,可能永远不会发生这种情况persist(),我猜这会正确初始化版本字段)

于 2015-03-11T17:01:12.183 回答