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

时间:2015-03-11 10:38:54

标签: java spring hibernate jpa roo

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

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

如果我正确地做事,在我的控制器类中,我有方法(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()读取数据的那一刻,问题可能与实体分离有关,但这只是一个假设。

提前致谢,

1 个答案:

答案 0 :(得分:1)

我想我已经找到了解决方案,感谢这个帖子:JPA Hibernate merge performs insert instead of update

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

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