每当我使用持久模型更新我的用户实体时,我都会得到ERROR: duplicate key value violates unique constraint "users_pkey"
Detail: Key (userid)=(2701) already exists.
。
在下面的代码示例中:SetLoginAttempts接受已查询的用户实体,当我启动事务时,我只需设置实体的一个字段并调用persist(),然后提交事务。
/**
* @param user
* @param attemptNumber
*/
@Transactional
public void setLoginAttempts(Users user, int attemptNumber){
user.setLoginAttempts(attemptNumber);
System.out.println(user);
}
以下是我如何引用和获取实体管理器:
eFactory = Persistence.createEntityManagerFactory("persistenceUnit");
eManager = eFactory.createEntityManager();
当查看堆栈跟踪时,我注意到提交实际上注入了一个插入
Call: INSERT INTO USERS (userID, EMAIL, ISLOCKED, LOGINATTEMPTS, passwordHash, passwordSalt, USERNAME, version) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
bind => [2701, admin@d.com, false, 1, $shiro1$SHA-256$500000$6mqzZ/d/3BLQuJqLh1dDhQ==$NKW7Z++o/JTvf884aDWhP3Uhpyb5fTPMrm4joWnw7nI=, [B@1a8e3115, admin, 1]
在Spring roo中引用实体管理器,更新字段并提交更改的正确方法是什么?
修改
我在方法中添加了@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: admin@d.com, Id: 2701, IsLocked: false, LoginAttempts: 2, Password: $shiro1$SHA-256$500000$6mqzZ/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
但即使刷新后仍然没有更新数据库,为什么交易关闭和更新数据库?
答案 0 :(得分:16)
JPA公开了两种方法...... persist()和merge()
Persist:Persist负责向DB插入新行,然后在JPA会话中将实体与状态相关联。
合并:合并获取现有实体并更新数据库行。它还会在JPA会话中更新实体的状态。
我认为用户已存在于您的数据库表中。为了更新登录计数,您可以在EntityManager上使用merge()
方法。
答案 1 :(得分:2)
如果上述两个都不起作用,请尝试(通过调整,因为它与我的代码相关):
Query query = entityManager.createQuery("UPDATE User x SET x.activated = 1 "+ "WHERE username=:usernameParam ");
query.setParameter("usernameParam", ""+user.username);
query.executeUpdate();
答案 2 :(得分:0)
EntityManager.persist()用于创建新的实体bean。
创建新的实体bean涉及在数据库中插入新行。
使用EntityManager.merge()更新已存在的实体bean。
调用EntityManager.merge()更新数据库以反映对分离的实体bean所做的更改。
如果您的实体bean没有分离,则无需调用merge()。
如果您的用户bean没有分离,您只需通过调用 setLoginAttempts()等方法来修改其属性。
EntityManager和容器将自动更新数据库(提交事务时)。