来自多个数据库的Hibernate实体

我们的数据模型在两个数据库中分为模式。 这些模式是隔离使用的,除了在两者之间桥接的一些单键关系。 没有跨两个数据库的写入事务。

与此问题类似, 使用Hibernate在不同数据库中进行2个表的连接 ,我们希望使用Hibernate来处理连接实体。 我们不能使用数据库解决方案(DB2上的联合视图)。

我们已经使用两个独立的数据库配置(Doctor和Patient)设置了Hibernate,这在使用DAO显式访问特定会话时非常有效。

当我们调用DoctorBO.getExam().getPatient()时,我们希望使用Hibernate自动检索实体DoctorBO.getExam().getPatient()其中,检查包含指向另一个数据库上Patient表的id。

我尝试这样做的一种方法是使用自定义UserType:

 public class DistributedUserType implements UserType, ParameterizedType { public static final String CLASS = "CLASS"; public static final String SESSION = "SESSION"; private Class 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 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; 

UserType工作 – 数据正确加载,只有字段的Id持久保存到数据库。 我已经测试了非常简单的doctor.getExam().getPatient()doctor.getExam().setPatient() ,两者似乎工作得很好,但是我认为这是一个可怕的黑客,我对Hibernate没有足够的知识知道这是否安全。

有没有更好的方法来实现我们想要的? 我在这里描述的方式是否足够,或将来会造成困难?

我不认为这是个好主意。 你试图让“仿佛”一切都在一个数据库中,而事实并非如此。 并且你做“好像”考试和病人之间存在真正的toOne关联,尽管它不是真正的关联。

虽然你意识到这个事实,但其他或未来的开发人员不一定会,并且会想知道为什么不可能进行查询,例如

 select e from Exam e left join fetch e.patient 

要么

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

简而言之,您的伪协会只能履行常规协会提供的合同的很小一部分,而IMO会导致更多的混乱而不是安慰。

没有什么可以阻止你使用像这样的实用方法

 Patient getExamPatient(Exam e) 

它做了同样的事情,但明确表示两个实体之间没有真正的联系。