2011-12-01 22 views
7

मेरे पास एक परिदृश्य के लिए 'सर्वोत्तम अभ्यास' प्रश्न है।हाइबरनेट मैपिंग: एकाधिक कॉलम में एक कॉलम

परिदृश्य: डीबी में एकाधिक संस्थाएं, उदाहरण के लिए, दस्तावेज़, ब्लॉगपोस्ट, विकी व्यक्तियों द्वारा साझा की जा सकती है। प्रत्येक इकाई के लिए शेयर तालिका बनाने के बजाय, एक ही साझा तालिका बनाई जाती है। मुद्दा यह है कि विभिन्न संस्थाओं के साथ शेयर तालिका को कैसे मैप करना है?

मेरे पास तीन विकल्प हैं, कृपया सलाह दें कि कौन सा विकल्प सबसे अच्छा है, और यदि कोई बेहतर विकल्प है।

Option1: के रूप में मेज शेयरों बनाएँ:

SHARES 
id (unique) 
entityId (non DB enforced FK to DOCUMENTS, WIKIS, POSTS etc.) 
entityType 
sharedBy 
sharedWith 
sharedDate 

यहाँ, entityId documentId, wikiId, postid आदि आदि करने के लिए एक FK हो जाएगा और entityType होगा पहचान entityId है कि किस प्रकार।

यह हाइबरनेट मॉडलिंग में मुद्दे हैं, जब इस तरह share.getDocument() या share.getWiki() आदि के रूप में इकाई मानचित्रण, करने के लिए शेयर बनाने

विकल्प 2: तालिका शेयरों बनाएं केवल हिस्सेदारी रखता है जो जानकारी, और फिर संकल्प सारणी बनाएं जो इकाई को साझा करें।

SHARES 
id(PK) 
sharedBy 
sharedWith 
sharedDate 
shareType (helper field for searches) 

SHARES_DOCUMENTS 
share_id (unique ID and FK, one to one with SHARES) 
document_id (FK to DOCUMENTS) 

SHARES_POST 
share_id (unique ID and FK, one to one with SHARES) 
post_id (FK to POSTS) 

more share tables here. 

तो, बुद्धिमान हाइबरनेट, शेयर शेयर प्रकारों में से प्रत्येक के लिए एक करने के लिए एक हो सकता है (share.getDocument(), share.getPost() की तरह है, और shareType की पहचान करेगा जो संबंध 'सक्रिय' है)

विकल्प 3 विकल्प 1 की तरह, लेकिन इकाई आईडी

SHARES 
id (unique ID) 
documentId (FK to DOCUMENTS, nullable) 
postId (FK to POSTS, nullable) 
wikiId (FK to WIKIS, nullable) 
sharedBy 
sharedWith 
sharedDate 
sharedType 

यहाँ के बजाय अलग-अलग स्तंभों बनाने के लिए, प्रत्येक स्तंभ संबंधित संस्था के लिए मैप किया जा सकता है, लेकिन वे व्यर्थ कर रहे हैं। साझा प्रकार पहचान सकता है कि कौन सा रिश्ता 'सक्रिय' है।

तो सवाल यह है कि कौन सा अभ्यास डेटाबेस के साथ-साथ हाइबरनेट मैपिंग (और अंतिम पूछताछ, प्रदर्शन के अनुसार) दोनों सर्वोत्तम है।

धन्यवाद एम बल्कि

+1

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/inheritance.html –

+0

पर एक नज़र डालें धन्यवाद, इसमें देखेंगे। लेकिन क्या यह वास्तव में एक विरासत मुद्दा है? या विरासत का उपयोग इसे हल करने के लिए किया जा सकता है। यदि प्रत्येक रिज़ॉल्यूशन टेबल में अतिरिक्त व्युत्पन्न जानकारी होती है, तो वे विरासत के लिए अर्हता प्राप्त कर सकते हैं, लेकिन वे केवल अलग-अलग इकाइयों के साथ संबंध रखते हैं। इसके अलावा, अधिकांश विरासत उदाहरण/दस्तावेज विभिन्न संस्थाओं के लिए एक कॉलम लिंक बनाने की कोशिश नहीं करते हैं। उनके पास वास्तव में स्वतंत्र क्षेत्र हैं जो उन्हें आगे परिभाषित करते हैं। –

+0

एक दूसरे विचार पर, विभिन्न संस्थाओं के संबंध 'उन्हें आगे परिभाषित' करते हैं। मैं एकल तालिका विकल्प के साथ कई कक्षाओं में देखता हूं, और देखता हूं कि यह कैसे काम करता है। –

उत्तर

4

TheStijn ने सुझाव दिया है, सेटअप विरासत रिश्तों को अलग अलग तरीकों में देखने के बाद, मैं दृष्टिकोण 'वर्ग पदानुक्रम प्रति एकल टेबल' के साथ चला गया, और तरह की मेज के साथ समाप्त हो गया:

SHARES 
--------- 
id PK 
shared_by FK to User 
shared_with FK to User 
shared_Date 
document_id nullable FK to Document 
post_id nullable FK to Posts 
... more ids here to link to more entities 
type_discriminator (values, DOCUMENT, POST ...) 

हाइबरनेट/जावा पर पक्ष, एक शेयर के रूप में सार वर्ग ...

@Entity 
@Table(name="SHARES") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="TYPE_DISCRIMINATOR", discriminatorType=DiscriminatorType.STRING) 
public abstract class Share { 
    @Id 
    @Column(name="ID", nullable=false) 
    @GeneratedValue(generator="system-uuid") 
    @GenericGenerator(name="system-uuid", strategy = "uuid") 
    private String id; 

    @ManyToOne 
    @JoinColumn(name="SHARED_BY", nullable=false) 
    private User sharedBy; 

    @ManyToOne 
    @JoinColumn(name="SHARED_WITH", nullable=false) 
    private User sharedWith; 

    @Column(name="SHARED_DATE", columnDefinition="TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP", nullable=false) 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date sharedDate;   
    ... 

} 

और दो सामान्य वर्गों ..

@Entity 
@DiscriminatorValue("DOCUMENT") 
public class SharedDocument extends Share { 
    @ManyToOne 
    @JoinColumn(name="DOCUMENT_ID", nullable=true) 
    private Document document; 
    .... 

} 

@Entity 
@DiscriminatorValue("POST") 
public class SharedPost extends Share { 
    @ManyToOne 
    @JoinColumn(name="POST_ID", nullable=true) 
    private Post post; 
    .... 

} 
,210

उपयोग के लिए के रूप में, के रूप में ही ठोस वर्ग का उपयोग करें:

@Test 
public void saveNewDocumentShare(){ 
    SharedDocument sharedDocument = new SharedDocument(); 
    sharedDocument.setDocument(document1); 
    sharedDocument.setSharedBy(teacher1); 
    sharedDocument.setSharedWith(teacher2); 
    sharedDocument.setSharedDate(new Date()); 

    sharedDocument.setCreatedBy("1"); 
    sharedDocument.setCreatedDate(new Date()); 
    sharedDocument.setModifiedBy("1"); 
    sharedDocument.setModifiedDate(new Date()); 


    SharedDocument savedSharedDocument = dao.saveSharedDocument(sharedDocument); 

    assertNotNull(savedSharedDocument); 
    assertThat(savedSharedDocument.getId(),notNullValue()); 
} 

@Test 
public void saveNewPostShare(){ 
    SharedPost sharedWikiPage = new SharedWikiPage(); 
    sharedPost.setPost(post1); 
    sharedPost.setSharedBy(teacher1); 
    sharedPost.setSharedWith(teacher2); 
    sharedPost.setSharedDate(new Date()); 

    sharedPost.setCreatedBy("1"); 
    sharedPost.setCreatedDate(new Date()); 
    sharedPost.setModifiedBy("1"); 
    sharedPost.setModifiedDate(new Date()); 


    SharedPost savedSharedPost = dao.saveSharedPost(sharedPost); 

    assertNotNull(savedSharedPost); 
    assertThat(savedSharedPost.getId(),notNullValue()); 

} 
0

यह स्पष्ट रूप से एक बहुत-से-अनेक संबंध है।

उन प्रकार की चीजों को मैप करने के लिए डिफ़ॉल्ट परिदृश्य कनेक्शन जानकारी के लिए एक अलग तालिका का उपयोग करना है। कुछ की तरह:

table shared_connections { 
    number owner_id 
    ,number shared_id 
} 

सभी वस्तुओं है कि साझा करने योग्य कुछ बुनियादी वर्ग पूर्व का विस्तार करना चाहिए: AbstractSharedObject। (@MappedSuperclass एनोटेशन और @ इनहेरिटेंस रणनीति के बारे में परवाह करें) का उपयोग करें।

और व्यक्तिगत वर्ग के अंदर:

private Collection<AbstractSharedObject> shares; 

नक्शा ManyToMany संबंध के रूप में इस संग्रह।

पीएस इसके लिए आपको काम करने की आवश्यकता होगी कि सभी साझा करने योग्य वस्तुओं की आईडी अद्वितीय हैं।

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