Как работать с несколькими схемами БД в Hibernate? - PullRequest
2 голосов
/ 02 ноября 2009

В одном из моих проектов у меня есть приложение, которое управляет несколькими клиентами (или клиентами, если вы предпочитаете). Для каждого из них у меня есть отдельная схема в базе данных. Однако приложение обрабатывает только одного клиента за раз, то есть пользователь должен переключаться с одного клиента на другой в приложении (во время выполнения, без перезапуска приложения), чтобы получить доступ к данным из этого нового клиента.

Как бы вы управляли соединениями, а также постоянным слоем для такого проекта?

Я хочу использовать Hibernate для этого. С какими моментами я должен быть очень осторожен при работе с несколькими базами данных / схемами?

Может ли Spring помочь в этом случае?

<Ч />

Если я не достаточно ясен, позвольте мне объяснить ситуацию на примере. Представьте, что мое приложение может обрабатывать двух клиентов: clientONE и clientTWO. Я уже реализовал класс, который может предоставить мне схему базы данных, пользователя, пароль и строку подключения для данного клиента.

У каждого клиента есть список должников, но, к сожалению, структура таблиц DEBTOR не одинакова для clientONE и clientTWO. Даже имена таблиц / столбцов не совпадают ...

Таким образом, я могу создать один класс должника для каждого клиента (я использую аннотации Hibernate):

@Entity
@Table(name = "T_DEBTOR_ONE")
...
public class ClientOneDebtor {

    @Id
    @Column(name = "ID_DEBTOR")
    private String idDebtor;

    ...

}

и

@Entity
@Table(name = "T_DEBTOR_TWO") // Table names are not the same among the different schemas...
...
public class ClientTwoDebtor {

    @Id
    @Column(name = "DEBTOR_ID") // It's just to show that the same information is stored in a column that has not the same name.
    private String idDebtor;

    ...

}

В идеале я постараюсь создать общий класс Debtor (здесь приведен класс Abstract, но я могу использовать интерфейс):

public abstract class AbstractDebtor {

    public abstract String getIdDebtor();

    ...

}


@Entity
@Table(name = "T_DEBTOR_ONE")
...
public class ClientOneDebtor extends AbstractDebtor {

    @Id
    @Column(name = "ID_DEBTOR")
    private String idDebtor;

    ...

}


@Entity
@Table(name = "T_DEBTOR_TWO")
...
public class ClientTwoDebtor extends AbstractDebtor {

    @Id
    @Column(name = "DEBTOR_ID") // It's just to show that the same information is stored in a column that has not the same name.
    private String idDebtor;

    ...

}

Таким образом, мне будет проще манипулировать объектами Debtor на моем уровне DAO / Service, так как мне не нужно будет дублировать мои DAO и Services для каждого клиента. Например, метод из DAO для получения списка всех должников будет public List<AbstractDebtor> getAllDebtors() { ... }.

Итак, как бы я изменил контекст при изменении клиента, управляемого моим приложением? Другими словами, как бы я указал Hibernate (или Spring?), Что я хочу использовать правильные объекты персистентности (ClientOneDebtor или ClientTwoDebtor) в отношении клиента, которым в данный момент управляет мое приложение?

Если вы думаете, что я иду в неправильном направлении, не стесняйтесь поделиться своими идеями о том, как решить эту проблему ...

<Ч />

Изменить относительно первых ответов:

Количество различных схем, которые мне нужно будет обработать, составляет около 15-20. Кроме того, мне нужно будет отобразить только небольшое подмножество их таблиц.

Я также знаю, что наличие одной схемы для каждого клиента / клиента - не лучшее решение для хранения данных. Однако эта архитектура существует уже 5 лет, и мы можем перейти только к одной схеме в течение следующего года (в лучшем случае;)).

Ответы [ 2 ]

1 голос
/ 02 ноября 2009

Если потребуется только по одному, то это будет намного проще. Просто создайте SessionFactory для каждой базы данных. Избегайте подхода HibernateUtils static SessionFactory instance, и у вас не возникнет никаких проблем.

Отличный способ сделать это с помощью Spring, если у вас не слишком много баз данных (сотни), - создать отдельный экземпляр Spring ApplicationContext для каждой, которая содержит конфигурации SessionFactoryBean и DataSource специально для этой базы данных. .

Вы можете использовать пружинные механизмы, такие как PropertyOverrideConfigurer и общий родительский элемент ApplicationContext, чтобы выделить все общие элементы, чтобы ваши потомки ApplicationContext были маленькими и обслуживаемыми.

Затем, когда поступит запрос, просто выберите ApplicationContext, с которым вы хотите работать, и начните извлекать из него бобы.

Если вы хотите сделать это без Spring, вы также можете создать несколько SessionFactory экземпляров и сохранить «текущий» экземпляр в статическом ThreadLocal.

0 голосов
/ 02 ноября 2009

К сожалению, в реальном мире часто требуется несколько баз данных / схем, особенно если у вас есть продукт поставщика, база данных которого должна отличаться от ваших корпоративных баз данных.

Создание произвольного количества баз данных было бы беспорядком, и для этого вы действительно ДОЛЖНЫ рассмотреть лучшую форму организации данных. Но для фиксированного (мы надеемся, небольшого) набора баз данных просто определите их в конфигурации постоянства с отдельным PersistenceUnit для каждой (что подразумевает отдельный EntityManager).

Используя вашу иллюстрированную схему наследования, вы назначаете соответствующий EntityManager каждому производному классу, предполагая, что инфраструктура позволяет вам.

...