【问题标题】:Hibernate Entities from Multiple Databases从多个数据库休眠实体
【发布时间】:2012-01-24 01:03:18
【问题描述】:

我们的数据模型分为两个数据库上的模式。除了在两者之间架起桥梁的一些单键关系外,这些模式是单独使用的。没有跨越两个数据库的写入事务。

类似于这个问题Doing a join over 2 tables in different databases using Hibernate,我们想使用 Hibernate 来处理加入实体。我们不能使用数据库解决方案(DB2 上的联合视图)。

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

我们希望在调用DoctorBO.getExam().getPatient() 时使用 Hibernate 自动检索实体,其中检查包含指向另一个数据库上的 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 没有足够的了解,无法知道这是否可以安全使用。

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

【问题讨论】:

    标签: java database hibernate usertype


    【解决方案1】:

    我认为这不是一个好主意。您试图使“好像”所有内容都在单个数据库中,但事实并非如此。并且您“好像”在检查和患者之间存在真正的 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)
    

    它做同样的事情,但清楚地表明两个实体之间没有真正的关联。

    【讨论】:

    • 我想我太聪明了。由于您所说的原因,此解决方案比我提出的解决方案要好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多