Nuestro modelo de datos está separado en esquemas en dos bases de datos. Los esquemas se usan de forma aislada, excepto por unas pocas relaciones de llave única que se conectan entre los dos. No hay transacciones de escritura que abarquen ambas bases de datos.Entidades de hibernación de múltiples bases de datos
Similar a esta pregunta Doing a join over 2 tables in different databases using Hibernate, queremos utilizar Hibernate para gestionar la unión de las entidades. No podemos usar la solución de base de datos (vistas federadas en DB2).
Hemos configurado Hibernate con dos configuraciones de base de datos separadas (Doctor y paciente), que funciona perfectamente cuando se utilizan DAO para acceder explícitamente a una sesión en particular.
Queremos utilizar Hibernate para recuperar automáticamente la entidad cuando llamamos al DoctorBO.getExam().getPatient()
Donde el examen contiene una identificación que apunta a la tabla del paciente en la otra base de datos.
Una forma que he intentado hacer esto es usar un UserType personalizado:
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);
}
}
que luego se utiliza:
@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;
El UserType funciona - los datos se cargan correctamente con sólo el Identificación del campo persistido en la base de datos. He probado ejemplos muy simples de doctor.getExam().getPatient()
y doctor.getExam().setPatient()
y ambos parecen funcionar muy bien, sin embargo, creo que este es un hack terrible y no tengo el conocimiento adecuado de Hibernate para saber si esto es seguro de usar.
¿Hay una mejor manera de lograr lo que queremos? ¿Es adecuada la manera que describí aquí o causará dificultades en el futuro?
+1 para una solución interesante. – Firo