2011-06-24 8 views
5

ताज़ा मैं निम्नलिखित डोमेन मॉडलत्रुटि जेपीए इकाई

Currency ----<Price>---- Product 

या अंग्रेजी में

A Product has one or more Prices. Each Price is denominated in a particular Currency.

Price एक समग्र प्राथमिक कुंजी (नीचे PricePK द्वारा प्रतिनिधित्व) जो विदेशी कुंजी के लिए बना है है Currency और Product। जेपीए-एनोटेट जावा वर्गों के प्रासंगिक अनुभाग नीचे (getters और setters ज्यादातर छोड़े गए) हैं:

@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public class Currency { 

    @Id 
    private Integer ix; 

    @Column 
    private String name; 

    @OneToMany(mappedBy = "pricePK.currency", cascade = CascadeType.ALL, orphanRemoval = true) 
    @LazyCollection(LazyCollectionOption.FALSE) 
    private Collection<Price> prices = new ArrayList<Price>(); 
} 

@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public class Product { 

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 

    @OneToMany(mappedBy = "pricePK.product", cascade = CascadeType.ALL, orphanRemoval = true) 
    @LazyCollection(LazyCollectionOption.FALSE) 
    private Collection<Price> defaultPrices = new ArrayList<Price>(); 
} 

@Embeddable 
public class PricePK implements Serializable { 

    private Product product;  
    private Currency currency; 

    @ManyToOne(optional = false) 
    public Product getProduct() { 
     return product; 
    } 

    @ManyToOne(optional = false) 
    public Currency getCurrency() { 
     return currency; 
    }  
} 

@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public class Price { 

    private PricePK pricePK = new PricePK(); 

    private BigDecimal amount; 

    @Column(nullable = false) 
    public BigDecimal getAmount() {  
     return amount; 
    } 

    public void setAmount(BigDecimal amount) {  
     this.amount = amount; 
    } 

    @EmbeddedId 
    public PricePK getPricePK() { 
     return pricePK; 
    }  

    @Transient 
    public Product getProduct() { 
     return pricePK.getProduct(); 
    } 

    public void setProduct(Product product) { 
     pricePK.setProduct(product); 
    } 

    @Transient 
    public Currency getCurrency() { 
     return pricePK.getCurrency(); 
    } 

    public void setCurrency(Currency currency) { 
     pricePK.setCurrency(currency); 
    } 
} 

मैं refresh को Product का एक उदाहरण का प्रयास करते हैं, मैं एक StackOverflowError मिलता है, तो मैं वहाँ चक्र के कुछ प्रकार है संदेह (या अन्य गलती) उपरोक्त मानचित्रण में, क्या कोई इसे खोज सकता है?

+0

+1, अच्छी तरह से सवाल उठाया। हालांकि, मैं डोमेन मॉडल के बारे में उत्सुक हूं। यह अजीब लगता है कि 'मूल्य' को 'उत्पाद' + 'मुद्रा' द्वारा स्पष्ट रूप से पहचाना जाता है, कहें, इसके (स्केलर) मान +' मुद्रा'। –

+0

धन्यवाद मैट, वास्तव में 'मूल्य' वर्ग में 'बिगडिसीमल राशि' फ़ील्ड भी है, लेकिन मैंने इसे यहां छोड़ दिया क्योंकि यह प्रश्न के लिए प्रासंगिक नहीं है, और मैं कोड सूची को जितना संभव हो सके –

उत्तर

2

मैंने यह त्रुटि कुछ बार देखी है, लेकिन मुझे सटीक समाधान याद नहीं है। मेरे पास यह विचार है कि आपको प्राइसपीके (दोनों @ManyToOne) से मानचित्रण को हटाने की आवश्यकता है और उस पर @AssociationOverrides मूल्य के साथ प्रतिस्थापित करें।

@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
@AssociationOverrides({ 
    @AssociationOverride(name = "pricePK.product", 
         joinColumns = @JoinColumn(name = "product_id")), 
    @AssociationOverride(name = "pricePK.currency", 
         joinColumns = @JoinColumn(name = "currency_id")) 
}) 
public class Price extends VersionedEntity { 
    [...] 
} 

कृपया जांचें कि कॉलम नाम ठीक हैं, क्योंकि मैं उत्पाद या मुद्रा पर आईडी कॉलम नहीं देख सकता।

+0

रखना चाहता हूं आईडी कॉलम दिखाने के लिए कक्षाओं को अपडेट किया गया –

+0

@ क्या आपने इस समाधान की कोशिश की है? साथ ही, मैंने स्वयं को सही तरीके से व्यक्त नहीं किया है, * कॉलम नाम * जो मैंने उल्लेख किया है वह मूल्य पर कॉलम के नाम हैं। इसलिए मैंने माना कि मूल्य तालिका पर आपके पास ** product_id ** और ** currency_id नामक दो कॉलम हैं। ** – Augusto

+0

मैंने आपके सुझाव की कोशिश की, लेकिन इसने यह त्रुटि उत्पन्न की: 'com.example.Currency के लिए प्रकार निर्धारित नहीं कर सका, तालिका में: PRICE, कॉलम के लिए: [org.hibernate.mapping.Column (मुद्रा)] ' –

0

क्या आपको मूल्य से उत्पाद और मुद्रा के संबंधों को सीधे मूल्य इकाई में कई लोगों के रूप में घोषित नहीं करना चाहिए, और @IdClass (PricePK) के साथ मूल्य एनोटेट करना चाहिए?

मुझे नहीं पता कि कैसे हाइबरनेट इसे संभालता है, लेकिन मैंने इसे OpenJPA का उपयोग करके सफलतापूर्वक कार्यान्वित किया है। उस स्थिति में, प्राइसपीके को अपने फ़ील्ड को मूल्य के समान नामों के साथ घोषित करना होगा, लेकिन इसके बजाय सरल प्रकार (मुद्रा या उत्पाद के बजाय इंटीजर) का उपयोग करना चाहिए। कीमत में, आपको @Id के साथ उत्पाद और मुद्रा को एनोटेट करने की आवश्यकता हो सकती है। ध्यान दें कि यह जेपीए स्पेक से बाहर है (@IdClass केवल सरल फ़ील्ड का समर्थन करता है)।

1

मुझे एक ही समस्या का सामना करना पड़ा और यह एक टॉमनी एनोटेशन में परिभाषित कैस्केड टाइप टाइप के कारण हुआ। जब आप उत्पाद को रीफ्रेश करते हैं, तो यह लगातार संदर्भ में मौजूद कीमतों को रीफ्रेश करने का प्रयास करेगा।

स्थिति पर निर्भर करता है, तो आप इस तरह के रूप कीमतों ताजा कर जब उत्पाद इकाई प्रबंधक में ताज़ा किया जाता है बिना द्वारा प्राप्त करने के लिए, सक्षम हो सकते हैं:

@OneToMany(mappedBy = "pricePK.product", cascade = { 
     CascadeType.PERSIST, CascadeType.MERGE 
    }, orphanRemoval = true) 
@LazyCollection(LazyCollectionOption.FALSE) 
private Collection<Price> defaultPrices = new ArrayList<Price>();