使用 Spring Roo 活动记录模式将实体保存回数据库

Saving entitities back to db with Spring Roo active record pattern

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

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

如果我做对了,在我的控制器 classes 中,我有方法 (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 键。使用 Roo 生成时,username 字段(不是键)被标记为 --unique。如果我尝试重新生成模式,删除 username 上的唯一要求,合并的效果是在数据库上创建第二条记录(没有给出任何例外),具有相同的用户名和不同的 Id 值(这显然不是我的应用程序所需的行为)。

2) 查看日志,hibernate(JPA 下使用的持久性提供程序)实际上尝试执行 sql INSERT 语句(我曾期望 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() 读取数据时实体分离有关,但这只是一个假设。

提前致谢,

我想我找到了解决方案,多亏了这个帖子:JPA Hibernate merge performs insert instead of update

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

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