Java 使用 EntityManager JPA EclipseLink 更新实体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9713617/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:35:43  来源:igfitidea点击:

Update Entity using EntityManager JPA EclipseLink

javajpaeclipselinkspring-roo

提问by Warz

I am getting a ERROR: duplicate key value violates unique constraint "users_pkey" Detail: Key (userid)=(2701) already exists.whenever i use the persist model to update my user entity.

ERROR: duplicate key value violates unique constraint "users_pkey" Detail: Key (userid)=(2701) already exists.每当我使用持久模型更新我的用户实体时,我都会得到一个。

In the code sample below: SetLoginAttempts takes in a user entity that has been queried and when i start the transaction i simply set one of the entity's fields and call persist(), then commit the transaction.

在下面的代码示例中: SetLoginAttempts 接收已查询的用户实体,当我开始事务时,我只需设置实体的字段之一并调用 persist(),然后提交事务。

/**
* @param user
* @param attemptNumber
*/
@Transactional
public void setLoginAttempts(Users user, int attemptNumber){         
    user.setLoginAttempts(attemptNumber);
    System.out.println(user);
}

Here is how i reference and grab the entity manager:

这是我引用和获取实体管理器的方式:

eFactory = Persistence.createEntityManagerFactory("persistenceUnit");
eManager = eFactory.createEntityManager();

When looking at the stack trace, i noticed that the commit actually injects an insert

在查看堆栈跟踪时,我注意到提交实际上注入了一个插入

Call: INSERT INTO USERS (userID, EMAIL, ISLOCKED, LOGINATTEMPTS, passwordHash, passwordSalt, USERNAME, version) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
bind => [2701, [email protected], false, 1, $shiro1$SHA-2560000mqzZ/d/3BLQuJqLh1dDhQ==$NKW7Z++o/JTvf884aDWhP3Uhpyb5fTPMrm4joWnw7nI=, [B@1a8e3115, admin, 1]

What is the proper way to reference an entity manager in Spring roo, update a field and commit the changes?

在 Spring roo 中引用实体管理器、更新字段并提交更改的正确方法是什么?

Edit

编辑

I added the @Transactional to the method and the stack trace shows that this is creating the entity manager instance:

我将 @Transactional 添加到方法中,堆栈跟踪显示这是创建实体管理器实例:

2012-03-14 23:49:15,503 ["http-bio-8080"-exec-18] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [org.bixin.dugsi.service.UserService.setLoginAttempts]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2012-03-14 23:49:15,503 ["http-bio-8080"-exec-18] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.eclipse.persistence.internal.jpa.EntityManagerImpl@46b9979b] for JPA transaction
[EL Finer]: 2012-03-14 23:49:15.503--ServerSession(2128384958)--Thread(Thread["http-bio-8080"-exec-18,5,main])--client acquired: 1116759395
[EL Finer]: 2012-03-14 23:49:15.503--ClientSession(1116759395)--Thread(Thread["http-bio-8080"-exec-18,5,main])--acquire unit of work: 368076985
2012-03-14 23:49:15,503 ["http-bio-8080"-exec-18] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Not exposing JPA transaction [org.eclipse.persistence.internal.jpa.EntityManagerImpl@46b9979b] as JDBC transaction because JpaDialect [org.springframework.orm.jpa.DefaultJpaDialect@c595bcd] does not support JDBC Connection retrieval
Email: [email protected], Id: 2701, IsLocked: false, LoginAttempts: 2, Password: $shiro1$SHA-2560000mqzZ/d/3BLQuJqLh1dDhQ==$NKW7Z++o/JTvf884aDWhP3Uhpyb5fTPMrm4joWnw7nI=, PasswordSalt: [B@1a8e3115, Roles: 0, Username: admin, Version: null
2012-03-14 23:49:15,503 ["http-bio-8080"-exec-18] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction commit
2012-03-14 23:49:15,503 ["http-bio-8080"-exec-18] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [org.eclipse.persistence.internal.jpa.EntityManagerImpl@46b9979b]
[EL Finer]: 2012-03-14 23:49:15.503--UnitOfWork(368076985)--Thread(Thread["http-bio-8080"-exec-18,5,main])--begin unit of work commit
[EL Finer]: 2012-03-14 23:49:15.503--UnitOfWork(368076985)--Thread(Thread["http-bio-8080"-exec-18,5,main])--end unit of work commit
[EL Finer]: 2012-03-14 23:49:15.504--UnitOfWork(368076985)--Thread(Thread["http-bio-8080"-exec-18,5,main])--resume unit of work
2012-03-14 23:49:15,504 ["http-bio-8080"-exec-18] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [org.eclipse.persistence.internal.jpa.EntityManagerImpl@46b9979b] after transaction
2012-03-14 23:49:15,504 ["http-bio-8080"-exec-18] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
[EL Finer]: 2012-03-14 23:49:15.504--UnitOfWork(368076985)--Thread(Thread["http-bio-8080"-exec-18,5,main])--release unit of work

But still no updates to the DB even after refresh, why isnt the transaction closing and updating the DB?

但是即使刷新后仍然没有更新数据库,为什么事务没有关闭和更新数据库?

采纳答案by Ameya

JPA exposes two methods... persist() and merge()

JPA 公开了两种方法……persist() 和 merge()

Persist: Persist is responsible for inserting new rows to DB and then associating the Entity with state in JPA session.

Persist:Persist 负责向 DB 插入新行,然后将 Entity 与 JPA 会话中的状态相关联。

Merge: Merge takes existing Entity and updates the DB row. It also updates the state of the entity in JPA session.

合并:合并采用现有实体并更新数据库行。它还更新 JPA 会话中实体的状态。

I think The user already exists in your database table. In order to update the login count, you can use the merge()method on EntityManager.

我认为该用户已存在于您的数据库表中。为了更新登录计数,您可以使用merge()EntityManager 上的方法。

回答by jahroy

EntityManager.persist() is used to create a new entity bean.

EntityManager.persist() 用于创建新的实体bean。

Creating a new entity bean involves inserting a new row in the database.

创建一个新的实体 bean 涉及在数据库中插入一个新行。

You use EntityManager.merge() to update an entity bean that already exists.

您使用EntityManager.merge() 更新已存在的实体 bean。

Calling EntityManager.merge() updates the database to reflect changes made to a detachedentity bean.

调用 EntityManager.merge() 更新数据库以反映对分离的实体 bean所做的更改。

If your entity bean is not detached, there's no need to invoke merge().

如果您的实体 bean 未分离,则无需调用 merge()。

If your user bean is not detached, you can simply modify its properties by calling methods like setLoginAttempts().

如果您的用户 bean 未分离,您可以通过调用setLoginAttempts() 之类的方法简单地修改其属性。

The EntityManager and container will update the database automatically (when the transaction is committed).

EntityManager 和容器将自动更新数据库(当事务提交时)。

回答by Damir Olejar

If neither of the mentioned works, try (by adjusting since it is relevant to my code):

如果上述方法均无效,请尝试(通过调整,因为它与我的代码相关):

            Query query = entityManager.createQuery("UPDATE User x SET x.activated = 1 "+ "WHERE username=:usernameParam ");
            query.setParameter("usernameParam", ""+user.username);
            query.executeUpdate();