使用EntityManager JPA EclipseLink更新实体

时间:2012-03-15 03:34:59

标签: java jpa eclipselink spring-roo

每当我使用持久模型更新我的用户实体时,我都会得到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

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

3 个答案:

答案 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和容器将自动更新数据库(提交事务时)。