我们的数据模型分为两个数据库中的模式。这些模式被单独使用,除了一些在两个数据库之间桥接的单键关系。没有涉及跨越两个数据库的写事务。
与这个问题 Doing a join over 2 tables in different databases using Hibernate 相似,我们想要使用Hibernate来处理实体之间的连接。我们不能使用数据库解决方案(如DB2上的联合视图)。
我们已经为Hibernate设置了两个单独的数据库配置(Doctor和Patient),当使用DAO明确访问特定会话时,它可以完美地工作。
我们想要使用Hibernate在调用
我尝试过的一种方法是使用自定义UserType:
与这个问题 Doing a join over 2 tables in different databases using Hibernate 相似,我们想要使用Hibernate来处理实体之间的连接。我们不能使用数据库解决方案(如DB2上的联合视图)。
我们已经为Hibernate设置了两个单独的数据库配置(Doctor和Patient),当使用DAO明确访问特定会话时,它可以完美地工作。
我们想要使用Hibernate在调用
DoctorBO.getExam().getPatient()
时自动检索实体,其中examination包含指向其他数据库中Patient表的id。我尝试过的一种方法是使用自定义UserType:
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;
用户类型(UserType)是有效的 - 只有字段的ID被持久化到数据库,数据被正确加载。我已经测试了非常简单的doctor.getExam().getPatient()
和doctor.getExam().setPatient()
的例子,它们都运行得很好,但我认为这是一种可怕的hack方法,并且我不太了解Hibernate是否安全使用。
有没有更好的方法来实现我们想要的?我描述的方法是否足够好,或者会在未来造成困难?