2009-11-02 3 views
2

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

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

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

Может ли весна оказать какую-либо помощь в этом случае?


Если я недостаточно ясен, позвольте мне объяснить ситуацию на примере. Представьте, что мое приложение может обрабатывать два клиента: 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 (здесь есть класс Аннотация, но я могу использовать интерфейс):

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 и сервисы для каждого клиента. Например, метод из DAO, чтобы получить список всех должников, будет public List<AbstractDebtor> getAllDebtors() { ... }.

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

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


Редактировать относительно первых ответов:

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

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

ответ

1

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

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

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

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

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

0

Из моего опыта, никогда не бывает особенно хорошей идеей иметь разные схемы для разных клиентов/пользователей/компаний/независимо. Сколько таких схем у вас есть? 2? 5? 100?

В приложениях, где у нас есть две или более схемы (размещение их на разных серверах или доступ к БД, размещенных третьими лицами в качестве типичных приложений), мы просто настраиваем независимые сеансовые заводы для каждого из них. Выбор правильного - это «неявно сделано» фабрикой сеансов, которая была введена в DAO. Таким образом, для вашей ситуации у вас может быть клиентOneDetborDAO и clientTwoDebtorDAO - это будет сложно для 100 клиентов;)

0

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

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

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

Смежные вопросы