2012-03-15 11 views
5

का उपयोग करके अद्यतन इकाई जब भी मैं अपनी उपयोगकर्ता इकाई को अद्यतन करने के लिए लगातार मॉडल का उपयोग करता हूं तो मुझे ERROR: duplicate key value violates unique constraint "users_pkey" Detail: Key (userid)=(2701) already exists. मिल रहा है।EntityManager JPA EclipseLink

नीचे दिए गए कोड नमूने में: SetLoginAttempts एक उपयोगकर्ता इकाई में लेता है जिसे पूछताछ की गई है और जब मैं लेनदेन शुरू करता हूं तो मैं बस इकाई के फ़ील्ड में से एक सेट करता हूं और लगातार() कॉल करता हूं, फिर लेनदेन करता हूं।

/** 
* @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, [email protected], false, 1, $shiro1$SHA-256$500000$6mqzZ/d/3BLQuJqLh1dDhQ==$NKW7Z++o/JTvf884aDWhP3Uhpyb5fTPMrm4joWnw7nI=, [[email protected], admin, 1] 

क्या है injects स्प्रिंग रू में किसी इकाई प्रबंधक का संदर्भ देने का एक उचित तरीका, एक फ़ील्ड अपडेट करें और परिवर्तन करें?

संपादित

मैं विधि के लिए @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 [[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 

लेकिन ताज़ा करने के बाद भी अभी भी DB में कोई अपडेट नहीं लेनदेन बंद करने और डीबी को अपडेट करने का लेनदेन क्यों नहीं है?

उत्तर

16

जेपीए दो तरीकों को उजागर करता है ... जारी रहती है() और विलय()

जारी रहती है: जारी रहती है DB के लिए नई पंक्तियाँ सम्मिलित करके और फिर जेपीए सत्र में राज्य के साथ इकाई जोड़ लिए जिम्मेदार है।

मर्ज करें: विलय मौजूदा इकाई लेता है और डीबी पंक्ति अपडेट करता है। यह जेपीए सत्र में इकाई की स्थिति को भी अद्यतन करता है।

मुझे लगता है कि उपयोगकर्ता आपकी डेटाबेस तालिका में पहले से मौजूद है। लॉगिन गिनती को अपडेट करने के लिए, आप EntityManager पर merge() विधि का उपयोग कर सकते हैं।

+0

मैं सिर्फ मर्ज के साथ() जारी रहती है की जगह की कोशिश की() और ऐसा लगता है कुछ भी नहीं के रूप में हुआ। स्टैक ट्रेस को फिर से देख रहे हैं और मुझे कुछ कारणों से यह "लेनदेन रोल वापस शुरू करना" मिलता है? मैं इसे वापस रोलिंग से कैसे रोकूं ताकि मैं डीबी – Warz

+0

में परिवर्तनों को देख सकूं कक्षा के अंदर निम्नलिखित लिखें: '@PersistenceContext (unitName =" myEntityManager ") निजी इकाई प्रबंधक इकाई Mgr; सार्वजनिक शून्य सेट लॉजिनएटम्प्ट्स (उपयोगकर्ता उपयोगकर्ता, int tryNumber) { user.setLoginAttempts (tryNumber); entityMgr.merge (उपयोगकर्ता); } सार्वजनिक उपयोगकर्ता getUser (ऑब्जेक्ट उपयोगकर्ता आईडी) { वापसी इकाई Mgr.find (User.class, userId); } ' – Ameya

0

EntityManager.persist() का उपयोग एक नई इकाई बीन बनाने के लिए किया जाता है।

एक नई इकाई बीन बनाने में डेटाबेस में एक नई पंक्ति डालने शामिल है।

आप पहले से मौजूद एक इकाई बीन को अद्यतन करने के लिए EntityManager.merge() का उपयोग करते हैं।

कॉलिंग EntityManager.merge() अलग इकाई बीन में किए गए परिवर्तनों को प्रतिबिंबित करने के लिए डेटाबेस अद्यतन करता है।

यदि आपकी इकाई बीन अलग नहीं है, तो मर्ज() को आमंत्रित करने की कोई आवश्यकता नहीं है।

यदि आपका उपयोगकर्ता बीन अलग नहीं है, तो आप setLoginAttempts() जैसी विधियों को कॉल करके अपनी गुणों को आसानी से संशोधित कर सकते हैं।

EntityManager और कंटेनर स्वचालित रूप से डेटाबेस अपडेट करेंगे (लेनदेन कब किया जाता है)।

+0

यदि मैं EntityManager प्राप्त किए बिना setLoginAttempts() को कॉल करता हूं, तो लॉग इन (प्रिंट प्रिंट स्टेटमेंट) को कॉल (प्रिंट स्टेटमेंट के साथ) कॉल करना जारी रहता है, हालांकि फ़ील्ड अपडेट किया जाता है, हालांकि डीबी को रीफ्रेश करना या ऐप को बंद करना नहीं है किए गए परिवर्तनों को प्रतिबिंबित करें? – Warz

+0

मैं कंटेनर को लेनदेन को संभालने की सलाह देना चाहता हूं (इसे स्वयं करने के चरण में)। मान लीजिए कि आप ईजेबी 3 का उपयोग कर रहे हैं, आप बस उचित लेनदेन एट्रिब्यूट के साथ विधि को एनोटेट कर सकते हैं और कंटेनर गंदा काम करेगा। दरअसल, डिफ़ॉल्ट लेनदेन एट्रिब्यूट टाइप आवश्यक है, जो स्वचालित रूप से लेनदेन में पूरी विधि को लपेट लेगा। – jahroy

+0

चेक इस बाहर: तो http://openejb.apache.org/transaction-annotations.html – jahroy

2

तो उल्लेख किया कार्यों का न तो, (का समायोजन करके के बाद से यह मेरी कोड के लिए प्रासंगिक है) की कोशिश:

  Query query = entityManager.createQuery("UPDATE User x SET x.activated = 1 "+ "WHERE username=:usernameParam "); 
      query.setParameter("usernameParam", ""+user.username); 
      query.executeUpdate(); 
संबंधित मुद्दे