2010-04-27 9 views
12

यह मान्य जैसे एक रिश्ते के दोनों ओर, पर @OneToOne और @NotNull घोषित करने के लिए है:हाइबरनेट @OneToOne @NotNull

class ChangeEntry 
{ 
    @OneToOne(cascade=CascadeType.ALL) 
    @NotNull 
    ChangeEntryDetails changeEntryDetails; 

    public void addDetails(ChangeEntryDetails details) { 
     this.changeEntryDetails = details; 
     details.setChangeEntry(this); 
    } 
} 

class ChangeEntryDetails 
{ 
    @OneToOne(cascase=CascadeType.ALL) 
    @NotNull 
    ChangeEntry changeEntry; 

    public void setChangeEntry(ChangeEntry changeEntry) 
    { 
      this.changeEntry = changeEntry; 
    } 
} 

मैं कुछ भी है कि कहना है कि यह अवैध है नहीं मिल सकता है, लेकिन यह है कि के दौरान लगता है संबंधों के कम से कम एक तरफ दृढ़ता का उल्लंघन किया जाना चाहिए। (उदाहरण के लिए, यदि लेखन लिखना पहले प्रवेश करें, तो बदलें एंटर्री विवरण अस्थायी रूप से शून्य हो जाएगा)।

यह कोशिश करते समय, मुझे not-null property references a null or transient value फेंक दिया गया अपवाद दिखाई देता है।

यदि संभव हो तो मैं बाधा को आराम से बचाना चाहता हूं, क्योंकि दोनों पक्ष मौजूद होना चाहिए।

+0

पर एक समस्याग्रस्त डेटा मॉडल की तरह लग सकते हैं। – Yishai

+0

दोनों तरफ कैस्केड होने के कारण थोड़ा अजीब है, लेकिन यह वास्तव में समस्याग्रस्त नहीं होना चाहिए। क्या आप विस्तारित कर सकते हैं? – Geoff

+0

कैस्केड वास्तव में क्षणिक संपत्ति को जारी रखने की कोशिश करने के लिए एक शॉटगन दृष्टिकोण था। यह विवरण रिकॉर्ड –

उत्तर

14

यह मान्य एक रिश्ता (...) मैं कुछ भी है कि कहना है कि यह अवैध है नहीं मिल सकता है के दोनों किनारों पर @OneToOne और @NotNull घोषित करने के लिए है, लेकिन ऐसा लगता है कि रिश्ते के हठ के दौरान कम से कम एक पक्ष उल्लंघन किया जाना चाहिए। (उदाहरण के लिए यदि changeEntry लिखना पहले, changeEntryDetails अस्थायी रूप से शून्य हो जाएगा)।

यह मान्य है और सब ठीक से मैप किए गए इकाइयों के साथ ठीक काम करता है। आपको अपने द्वि-दिशात्मक संगठन के एक पक्ष को "स्वामित्व" पक्ष के रूप में घोषित करने की आवश्यकता है (यह "नियंत्रण" आवेषण का क्रम)। एक संभव काम कर समाधान:

@Entity 
@NamedQueries({ @NamedQuery(name = ChangeEntry.FIND_ALL_CHANGEENTRIES, query = "SELECT c FROM ChangeEntry c") }) 
public class ChangeEntry implements Serializable { 
    public final static String FIND_ALL_CHANGEENTRIES = "findAllChangeEntries"; 

    @Id 
    @GeneratedValue 
    private Long id; 

    @OneToOne(optional = false, cascade = CascadeType.ALL) 
    @JoinColumn(name = "DETAILS_ID", unique = true, nullable = false) 
    @NotNull 
    private ChangeEntryDetails changeEntryDetails; 

    public void addDetails(ChangeEntryDetails details) { 
     this.changeEntryDetails = details; 
     details.setChangeEntry(this); 
    } 

    // constructor, getters and setters 
} 

और अन्य इकाई के लिए (ध्यान दें mappedBy विशेषता संघ के गैर-मालिक की ओर से सेट):

@Entity 
public class ChangeEntryDetails implements Serializable { 
    @Id 
    @GeneratedValue 
    private Long id; 

    @OneToOne(optional = false, mappedBy = "changeEntryDetails") 
    @NotNull 
    private ChangeEntry changeEntry; 

    // constructor, getters and setters 
} 
इन संस्थाओं, निम्नलिखित परीक्षण के साथ

(के लिए प्रदर्शन के उद्देश्य से) गुजरता है:

public class ChangeEntryTest { 
    private static EntityManagerFactory emf;  
    private EntityManager em; 

    @BeforeClass 
    public static void createEntityManagerFactory() { 
     emf = Persistence.createEntityManagerFactory("TestPu"); 
    }  
    @AfterClass 
    public static void closeEntityManagerFactory() { 
     emf.close(); 
    }  
    @Before 
    public void beginTransaction() { 
     em = emf.createEntityManager(); 
     em.getTransaction().begin(); 
    }  
    @After 
    public void rollbackTransaction() { 
     if (em.getTransaction().isActive()) { 
      em.getTransaction().rollback(); 
     } 
     if (em.isOpen()) { 
      em.close(); 
     } 
    } 

    @Test 
    public void testCreateEntryWithoutDetails() { 
     try { 
      ChangeEntry entry = new ChangeEntry(); 
      em.persist(entry); 
      fail("Expected ConstraintViolationException wasn't thrown."); 
     } catch (ConstraintViolationException e) { 
      assertEquals(1, e.getConstraintViolations().size()); 
      ConstraintViolation<?> violation = e.getConstraintViolations() 
       .iterator().next(); 

      assertEquals("changeEntryDetails", violation.getPropertyPath() 
       .toString()); 
      assertEquals(NotNull.class, violation.getConstraintDescriptor() 
       .getAnnotation().annotationType()); 
     } 
    } 

    @Test 
    public void testCreateDetailsWithoutEntry() {  
     try { 
      ChangeEntryDetails details = new ChangeEntryDetails(); 
      em.persist(details); 
      fail("Expected ConstraintViolationException wasn't thrown."); 
     } catch (ConstraintViolationException e) { 
      assertEquals(1, e.getConstraintViolations().size()); 
      ConstraintViolation<?> violation = e.getConstraintViolations() 
       .iterator().next(); 

      assertEquals("changeEntry", violation.getPropertyPath() 
       .toString()); 
      assertEquals(NotNull.class, violation.getConstraintDescriptor() 
       .getAnnotation().annotationType()); 
     } 
    } 

    @Test 
    public void validEntryWithDetails() { 
     ChangeEntry entry = new ChangeEntry(); 
     ChangeEntryDetails details = new ChangeEntryDetails(); 
     entry.addDetails(details); 
     em.persist(entry); 

     Query query = em.createNamedQuery(ChangeEntry.FIND_ALL_CHANGEENTRIES); 
     assertEquals(1, query.getResultList().size()); 
    } 
} 
+1

आप, महोदय, चट्टान। उत्कृष्ट उत्तर - बहुत बहुत धन्यवाद। यदि मैं पूछ सकता हूं - @OnToOne घोषणा पर @NotNull और वैकल्पिक = झूठी क्यों घोषित करें? क्या वे विभिन्न उद्देश्यों की सेवा करते हैं? –

+2

@ मार्टी आप का स्वागत है, खुशी है कि आपको यह उपयोगी लगता है।'@ NotNull' और' @JoinColumn (nullable = false) 'के उपयोग के संबंध में, [परिशिष्ट डी।] की मेरी समझ (http://people.redhat.com/~ebernard/validation/#appendix-jpa) बीन प्रमाणीकरण का नमूना यह है कि बीन प्रमाणीकरण-जागरूक डीडीएल उत्पन्न करना दृढ़ता प्रदाता के लिए अनिवार्य नहीं है, इसलिए मैं केवल जेपीए और बीवी एपीआई दोनों का उपयोग करता हूं। –

0

यह आपके कैस्केड प्रकार की वजह से क्षणिक मूल्य को बनाए रखना चाहिए।

यदि आप वास्तव में अन्य क्षणिक तत्व सेट करने से पहले पहले तत्व को जारी रखने की कोशिश कर रहे हैं, तो आप इस त्रुटि की अपेक्षा करेंगे।

आपके द्वारा निर्दिष्ट बाधा केवल निर्दिष्ट करती है कि डेटा मॉडल की बजाय डेटाबेस में मान शून्य नहीं हो सकता है, स्पष्ट रूप से जब आप ऑब्जेक्ट का नया उदाहरण बनाते हैं, तो संदर्भ शून्य होगा। जबकि संदर्भ शून्य है आप इकाई को जारी नहीं रख सकते हैं।

+0

पर होना आवश्यक नहीं है डेटाबेस बनाम मॉडल पहलू को स्पष्ट करने के लिए धन्यवाद। समझ में आता है। –

0

आप यहाँ openJPA और पास्कल समाधान के साथ एक ही समस्या हो रही हो गया तो अभी भी आपके लिए काम नहीं कर रहा है, आप ओपनजेपीए संपत्ति openjpa.InverseManager से true को अपने persistence.xml

संबंधित मुद्दे