2012-03-15 48 views
5

Tôi nhận được ERROR: duplicate key value violates unique constraint "users_pkey" Detail: Key (userid)=(2701) already exists. bất cứ khi nào tôi sử dụng mô hình cố định để cập nhật thực thể người dùng của mình.Cập nhật thực thể bằng EntityManager JPA EclipseLink

Trong mẫu mã bên dưới: SetLoginAttempts lấy một thực thể người dùng đã được truy vấn và khi tôi bắt đầu giao dịch, tôi chỉ cần đặt một trong các trường của thực thể và gọi persist(), sau đó cam kết giao dịch.

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

Dưới đây là làm thế nào tôi tham khảo và lấy người quản lý thực thể:

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

Khi nhìn vào stack trace, tôi nhận thấy rằng các cam kết thực sự tiêm nhiễm một chèn

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

là gì cách thích hợp để tham chiếu trình quản lý thực thể trong Spring roo, cập nhật trường và cam kết các thay đổi?

Sửa

tôi thêm @Transactional đến phương pháp và stack trace cho thấy rằng điều này đang tạo ra những trường hợp quản lý thực thể:

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 [[email protected]] 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 [[email protected]] as JDBC transaction because JpaDialect [[email protected]] does not support JDBC Connection retrieval 
Email: [email protected], Id: 2701, IsLocked: false, LoginAttempts: 2, Password: $shiro1$SHA-256$500000$6mqzZ/d/3BLQuJqLh1dDhQ==$NKW7Z++o/JTvf884aDWhP3Uhpyb5fTPMrm4joWnw7nI=, PasswordSalt: [[email protected], 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 [[email protected]] 
[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 [[email protected]] 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 

Nhưng vẫn không có bản cập nhật cho DB ngay cả sau khi làm mới , tại sao không phải là giao dịch đóng và cập nhật DB?

Trả lời

16

JPA cho thấy hai phương pháp ... tồn tại() và sáp nhập()

Persist: Cố chịu trách nhiệm về chèn hàng mới vào DB và sau đó kết hợp các thực thể với nhà nước trong phiên JPA.

Hợp nhất: Hợp nhất nhận thực thể hiện tại và cập nhật hàng DB. Nó cũng cập nhật trạng thái của thực thể trong phiên JPA.

Tôi nghĩ Người dùng đã tồn tại trong bảng cơ sở dữ liệu của bạn. Để cập nhật số lượng đăng nhập, bạn có thể sử dụng phương thức merge() trên EntityManager.

+0

Tôi chỉ cố gắng thay thế tồn tại() với merge() và nó có vẻ như không có gì xảy ra. Nhìn vào dấu vết ngăn xếp một lần nữa và tôi nhận được điều này "Bắt đầu một cuộn giao dịch trở lại" vì một lý do nào đó? làm thế nào để tôi ngăn chặn nó quay trở lại vì vậy tôi có thể thấy những thay đổi trong DB – Warz

+0

Viết sau đây trong lớp học: '@PersistenceContext (unitName =" myEntityManager ") thực thể EntityManager riêngMgr; public void setLoginAttempts (Người dùng người dùng, int tryNumber) { user.setLoginAttempts (tryNumber); entityMgr.merge (người dùng); } người dùng công cộng getUser (Object userId) { trả về thực thểMgr.find (User.class, userId); } ' – Ameya

0

EntityManager.persist() được sử dụng để tạo bean thực thể mới.

Tạo bean thực thể mới liên quan đến việc chèn hàng mới vào cơ sở dữ liệu.

Bạn sử dụng EntityManager.merge() để cập nhật bean thực thể đã tồn tại.

Gọi EntityManager.merge() cập nhật cơ sở dữ liệu để phản ánh các thay đổi được thực hiện cho một hạt thực thể tách rời.

Nếu bean thực thể của bạn không bị tách rời, không cần phải gọi hàm merge().

Nếu bean người dùng của bạn không bị tách rời, bạn có thể chỉ cần sửa đổi thuộc tính của nó bằng cách gọi các phương thức như setLoginAttempts().

EntityManager và vùng chứa sẽ tự động cập nhật cơ sở dữ liệu (khi giao dịch được thực hiện).

+0

Nếu tôi chỉ cần gọi setLoginAttempts() mà không cần có EntityManager, hãy gọi persist() hoặc merge() các bản ghi hiển thị (với lệnh in) rằng trường được cập nhật, Tuy nhiên làm mới DB hoặc tắt ứng dụng không phản ánh những thay đổi được thực hiện? – Warz

+0

Tôi khuyên bạn nên để hộp chứa xử lý giao dịch (thay vì tự thực hiện giao dịch). Giả sử bạn đang sử dụng EJB 3, bạn có thể chỉ cần chú thích phương thức với TransactionAttribute thích hợp và vùng chứa sẽ thực hiện công việc dơ bẩn. Trên thực tế, TransactionAttributeType mặc định là REQUIRED, sẽ tự động quấn toàn bộ phương thức trong một Transaction. – jahroy

+0

Kiểm tra điều này: http://openejb.apache.org/transaction-annotations.html – jahroy

2

Nếu không có những tác phẩm đã đề cập, thử (bằng cách điều chỉnh vì nó có liên quan đến mã của tôi):

  Query query = entityManager.createQuery("UPDATE User x SET x.activated = 1 "+ "WHERE username=:usernameParam "); 
      query.setParameter("usernameParam", ""+user.username); 
      query.executeUpdate(); 
Các vấn đề liên quan