J B*_*lay 9 java database hibernate usertype
我们的数据模型在两个数据库中分为模式.这些模式是隔离使用的,除了在两者之间桥接的一些单键关系.没有跨两个数据库的写入事务.
与此问题类似,使用Hibernate在不同数据库中对2个表进行连接,我们希望使用Hibernate来处理实体的连接.我们不能使用数据库解决方案(DB2上的联合视图).
我们已经使用两个独立的数据库配置(Doctor和Patient)设置了Hibernate,这在使用DAO显式访问特定会话时非常有效.
我们希望在调用时使用Hibernate自动检索实体DoctorBO.getExam().getPatient()Where检查包含指向另一个数据库上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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后将使用哪个:
@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;
Run Code Online (Sandbox Code Playgroud)
UserType工作 - 数据正确加载,只有字段的Id持久保存到数据库.我已经测试了非常简单的例子,doctor.getExam().getPatient()并且doctor.getExam().setPatient()两者似乎都很好用,但是我认为这是一个糟糕的黑客,而且我对Hibernate没有足够的了解,知道这是否安全.
有没有更好的方法来实现我们想要的?我在这里描述的方式是否足够,或将来会造成困难?
我不认为这是个好主意.你试图让"好像"所有东西都在一个数据库中,而事实并非如此.并且你做"好像" toOne考试和病人之间存在真正的关联,尽管它不是真正的关联.
虽然你意识到这个事实,但其他或未来的开发人员不一定会,并且会想知道为什么不可能做出如下的查询:
select e from Exam e left join fetch e.patient
Run Code Online (Sandbox Code Playgroud)
要么
select e from Exam e where e.patient.name like 'Smith%'
Run Code Online (Sandbox Code Playgroud)
简而言之,您的伪协会只能履行常规协会提供的合同的很小一部分,这将导致IMO更加困惑而不是安慰.
没有什么可以阻止你使用像这样的实用方法
Patient getExamPatient(Exam e)
Run Code Online (Sandbox Code Playgroud)
它做了同样的事情,但清楚地表明两个实体之间没有真正的联系.