JPA EntityManager:merge() 试图在数据库中创建一个新行 - 为什么?

san*_*ity 5 java jpa playframework

我正在通过 Play 框架使用 JPA。

我正在检查 User 对象是否被缓存,如果是,我检索它并合并()它以便我可以更新字段并稍后保存更改:

user = (User) Cache.get("user-auth-" + sessionAuthToken);
if (user != null) {
    user = user.merge();  // I believe this is the same as EntityManager.merge()
}
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做时,我收到以下错误:

PersistenceException occured : 
  org.hibernate.exception.ConstraintViolationException: 
    could not insert: [models.User]
...
Caused by: com.mysql.jdbc.exceptions.jdbc4.
   MySQLIntegrityConstraintViolationException: 
     Duplicate entry '1235411688335416533' for key 'authToken'
Run Code Online (Sandbox Code Playgroud)

它似乎试图插入一个新用户,即使这个用户应该是,并且已经在数据库中。为什么要 merge() 这样做?

或者我可能完全以错误的方式处理这个问题 - 建议将不胜感激。

Per*_*ega 3

我相信您的问题是 Play 管理 JPA 环境(和事务)的方式。

一旦收到请求,框架就会立即创建 JPA 管理器和事务。从那时起,您的所有模型实体都会自动链接到管理器。

Play 通过两种方式促进该模型的使用:

  • 您必须明确表明您想要保存对对象的更改(通过 save())
  • 事务会自动提交,除非出现异常或者您将其标记为回滚(JPA.setRollbackOnly())

通过运行“merge”,您试图向管理器添加一个已经存在的实体,这会导致唯一键异常。如果您只是从缓存中加载实体,完成后您将能够修改并调用 save() ,并且它将起作用。