Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
329 views
in Technique[技术] by (71.8m points)

java - How to handle several DB schemas with Hibernate?

In one of my projects, I have an application that manages several clients (or customer if you prefer). For each of them, I have a dedicated schema on a database. However, the application handles only one client at a time, i.e. the user must switch from one client to another in the application (at runtime, no restart of the application) in order to access the data from this new client.

How would you manage the connections, as well as the persistence layer, for this kind of project?

I want to use Hibernate for that. What are the points on which I must be really carefull when dealing with several database / schemas ?

Can Spring be of any help in this case?


If I am not clear enough, let me explain the situation with an example. Imagine that my application can handle two clients: clientONE and clientTWO. I already implemented a class that can provide me the database schema, user, password and connection String for a given client.

Each client have a list of debtors, but unfortunately, the DEBTOR table structure is not the same for clientONE and clientTWO. Even the names of tables / columns are not the same...

So I can create one debtor class per client (I use Hibernate annotations):

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

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

    ...

}

and:

@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;

    ...

}

Ideally, I will try to have a common Debtor class (here is an Abstract class, but I may use an Interface):

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;

    ...

}

This way, it will be easier for me to manipulate the Debtor objects in my DAO / Service layer, as I will not need to duplicate my DAO and Services for every client. For example, the method from DAO to get the list of all Debtors will be public List<AbstractDebtor> getAllDebtors() { ... }.

So, how would I change the context when I change the client managed by my application? In others words, how would I indicate to Hibernate (or Spring?) that I want to use the correct persistence objects (ClientOneDebtor or ClientTwoDebtor) regarding the client that is currently managed by my application?

If you think that I am going in the wrong direction, do not hesitate to share your ideas on how to solve this kind of problem...


Edit regarding the first answers:

The number of different schemas I will need to handle is around 15 - 20. In addition to that, I will only need to map only a little subset of their tables.

I also know that having one schema per client/customer is not the best solution for storing data. However, this architecture exist since 5 years, and we may move to only one schema during the next year (in the best case ;) ).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If only one at a time will every be required, it makes it much simpler. Simply create a SessionFactory per database. Avoid the HibernateUtils static SessionFactory instance approach and you won't have any problems.

A neat way to do this with Spring if you don't have too many databases (hundreds) is to instantiate a separate Spring ApplicationContext for each one that contains the SessionFactoryBean and DataSource configurations specially for that database.

You can use Spring mechanisms like PropertyOverrideConfigurer and a common parent ApplicationContext to factor out all the common stuff so that your many child ApplicationContexts are small and maintainable.

Then when a request comes in, just select the ApplicationContext you want to work with and start pulling beans out of it.

If you want to do it without Spring, you could also create multiple SessionFactory instances and store the "current" one in a static ThreadLocal.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...