2012-01-24 16 views
9

हमारे डेटा मॉडल को दो डेटाबेस पर स्कीमा में विभाजित किया गया है। स्कीमा का उपयोग अलगाव में किया जाता है, जो कि दो एकल-महत्वपूर्ण संबंधों को छोड़कर दो के बीच पुल करता है। कोई लेखन लेनदेन नहीं है जो दोनों डेटाबेस को फैलाएगा।एकाधिक डेटाबेस से हाइबरनेट इकाइयां

इस प्रश्न के समान Doing a join over 2 tables in different databases using Hibernate, हम इकाइयों में शामिल होने के लिए हाइबरनेट का उपयोग करना चाहते हैं। हम डेटाबेस समाधान (डीबी 2 पर संघीय विचार) का उपयोग नहीं कर सकते हैं।

हमने दो अलग डेटाबेस कॉन्फ़िगरेशन (डॉक्टर और रोगी) के साथ हाइबरनेट स्थापित किया है, जो किसी विशेष सत्र को स्पष्ट रूप से एक्सेस करने के लिए डीएओ का उपयोग करते समय पूरी तरह से काम करता है।

हम DoctorBO.getExam().getPatient() पर कॉल करते समय हम इकाई को स्वचालित रूप से पुनर्प्राप्त करने के लिए हाइबरनेट का उपयोग करना चाहते हैं, जहां परीक्षा में अन्य डेटाबेस पर रोगी तालिका को इंगित करने वाली आईडी होती है।

public class DistributedUserType implements UserType, ParameterizedType 
{ 
    public static final String CLASS = "CLASS"; 
    public static final String SESSION = "SESSION"; 

    private Class<? extends DistributedEntity> returnedClass; 
    private String session; 

    /** {@inheritDoc} */ 
    @Override 
    public int[] sqlTypes() 
    { 
     // The column will only be the id 
     return new int[] { java.sql.Types.BIGINT }; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public Class<? extends DistributedEntity> returnedClass() 
    { 
     // Set by typedef parameter 
     return returnedClass; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public boolean equals(Object x, Object y) throws HibernateException 
    { 
     if (x == y) 
     { 
      return true; 
     } 

     if ((x == null) || (y == null)) 
     { 
      return false; 
     } 

     Long xId = ((DistributedEntity) x).getId(); 
     Long yId = ((DistributedEntity) y).getId(); 

     if (xId.equals(yId)) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public int hashCode(Object x) throws HibernateException 
    { 
     assert (x != null); 
     return x.hashCode(); 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException 
    { 
     Long id = rs.getLong(names[0]); 
     return HibernateUtils.getSession(session).get(returnedClass, id); 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException 
    { 
     DistributedEntity de = (DistributedEntity) value; 
     st.setLong(index, de.getId()); 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public Object deepCopy(Object value) throws HibernateException 
    { 
     return value; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public boolean isMutable() 
    { 
     return false; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public Serializable disassemble(Object value) throws HibernateException 
    { 
     return (Serializable) value; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public Object assemble(Serializable cached, Object owner) throws HibernateException 
    { 
     return cached; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public Object replace(Object original, Object target, Object owner) throws HibernateException 
    { 
     return original; 
    } 

    /** {@inheritDoc} */ 
    @Override 
    public void setParameterValues(Properties parameters) 
    { 
     String clazz = (String) parameters.get(CLASS); 
     try 
     { 
      returnedClass = ReflectHelper.classForName(clazz); 
     } 
     catch (ClassNotFoundException e) 
     { 
      throw new IllegalArgumentException("Class: " + clazz + " is not a known class type."); 
     } 

     session = (String) parameters.get(SESSION); 
    } 
} 

कौन सा तो इस्तेमाल किया जाएगा:

एक तरह से मैं कोशिश यह कर दिया है एक कस्टम प्रयोक्ता प्रकार उपयोग कर रहा है

@TypeDef(name = "testUserType", typeClass = DistributedUserType.class, parameters = { 
                       @Parameter(name = DistributedUserType.CLASS, value = PatientBO.CLASSNAME), 
                       @Parameter(name = DistributedUserType.SESSION, value = HibernateUtils.PATIENT_SESS) }) 

@Type(type = "testUserType") 
@Column(name = "PATIENT_ID") 
private PatientBO patient; 

प्रयोक्ता प्रकार काम करता है - डेटा के साथ ही सही ढंग से भरी हुई है क्षेत्र का आईडी डेटाबेस के लिए जारी रखा। मैंने doctor.getExam().getPatient() और doctor.getExam().setPatient() के बहुत ही सरल उदाहरणों का परीक्षण किया है और दोनों महान काम करने लगते हैं, हालांकि मुझे लगता है कि यह एक भयानक हैक है और मेरे पास यह जानने के लिए सुरक्षित है कि यह जानने के लिए हाइबरनेट का पर्याप्त ज्ञान नहीं है।

क्या हम चाहते हैं कि हासिल करने के लिए एक बेहतर तरीका है? जिस तरह से मैंने यहां पर्याप्त वर्णन किया है, या भविष्य में कठिनाइयों का कारण बन जाएगा?

+0

+1। – Firo

उत्तर

5

मुझे नहीं लगता कि यह एक अच्छा विचार है। आप "जैसे" सब कुछ एक डेटाबेस में बनाने की कोशिश कर रहे हैं, जबकि यह मामला नहीं है। और आप "जैसे" बनाते हैं, एक परीक्षा और एक रोगी के बीच वास्तविक toOne एसोसिएशन था, हालांकि यह वास्तविक सहयोग नहीं है।

यद्यपि आप अन्य इस तथ्य के प्रति जागरूक कर रहे हैं या भविष्य डेवलपर्स जरूरी नहीं होगा, और आश्चर्य होगा क्यों यह एक प्रश्न बनाने के लिए संभव नहीं है इस तरह के रूप

select e from Exam e left join fetch e.patient 

या

select e from Exam e where e.patient.name like 'Smith%' 

संक्षेप में, आपका छद्म-संघ केवल अनुबंध के एक बहुत ही छोटे हिस्से को नियमित एसोसिएशन ऑफ़र पूरा करता है, और यह आईएमओ, आराम से ज्यादा भ्रम पैदा करेगा।

कुछ भी नहीं की तरह

Patient getExamPatient(Exam e) 

वही चीज़ एक उपयोगिता विधि होने से आप बंद हो जाता है, लेकिन दोनों संस्थाओं के बीच कोई वास्तविक asociation है यह स्पष्ट है कि बनाता है। दिलचस्प समाधान के लिए

+0

मुझे लगता है कि मैं बहुत चालाक होने की कोशिश कर रहा था। यह समाधान आपके द्वारा बताए गए कारणों के लिए प्रस्तावित एक से बेहतर है। –

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