Il nostro modello di dati è separato in schemi su due database. Gli schemi sono usati in isolamento, tranne per alcune poche relazioni a chiave singola che collegano tra loro. Non ci sono transazioni di scrittura che coprono entrambi i database.Sospensione di entità da più database
Simile a questa domanda Doing a join over 2 tables in different databases using Hibernate, vogliamo utilizzare Hibernate per gestire l'unione delle entità. Non possiamo usare la soluzione di database (viste federate su DB2).
Abbiamo impostato Hibernate con due configurazioni di database separate (Medico e Paziente), che funziona perfettamente quando si utilizzano DAO per accedere esplicitamente a una determinata sessione.
Vogliamo utilizzare Hibernate per recuperare automaticamente l'entità quando chiamiamo DoctorBO.getExam().getPatient()
Dove esame contiene un ID che punta alla tabella Paziente sull'altro database.
Un modo in cui ho provato a fare questo sta usando un UserType personalizzato:
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);
}
}
che sarebbe poi essere utilizzato:
@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;
L'UserType funziona - i dati vengono caricati correttamente con il solo L'ID del campo è rimasto nel database. Ho provato esempi molto semplici di doctor.getExam().getPatient()
e doctor.getExam().setPatient()
ed entrambi sembrano funzionare alla grande, tuttavia penso che questo sia un hack terribile e non ho una conoscenza adeguata di Hibernate per sapere se questo è sicuro da usare.
C'è un modo migliore per ottenere ciò che vogliamo? Il modo in cui ho descritto qui è adeguato, o causerà difficoltà in futuro?
+1 per una soluzione interessante. – Firo