How to configure two database in Hibernate - java

I have to configure two database on same project by configuring two CFG file,
I tried but it is always use the first configuration file,
May i know how can i use two database on same project

In your code, what you need to do is to open two different session factory for different databases.
For example:
Configuration configA=new Configuration();//use the default hibernate.cgf.xml file
Congiruration configB=new Configuration.configure('/hibernate_db2.cfg.xml') // use hibernate_db2.cfg.xml under root folder.
SessionFactory sfa=configA.buildSessionFactory();
SessionFactory sfb=configB.buildSessionFactory();
Now, you open different session using different db.

You need to have two configuration files.
hibernate-mysql.cfg.xml
hibernate-oracle.cfg.xml
And code should be like this.
mysql configuration
private static SessionFactory sessionAnnotationFactory;
sessionAnnotationFactory = new Configuration().configure("hibernate-mysql.cfg.xml").buildSessionFactory();
Session session = sessionAnnotationFactory.openSession();
oracle sql configuration
sessionAnnotationFactory = new Configuration().configure("hibernate-oracle.cfg.xml").buildSessionFactory();
Session session = sessionAnnotationFactory.openSession()

Related

Dynamically routed sqlSessionFactory in mybatis

Is it possible to choose Mapper to execute in Mybatis?
I am using dynamically routed datasource and give it as parameter to sqlSessionFactory - it is working.
The problem is, however, that different databases may require other SQL queries (very small differences, but differences).
Is it possible to create dynamically routed sqlSessionFactory - and give to them other package mappers?
This is how you obtain a session factory:
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
A couple of things are declared in in mybatis-config.xml, amongst whom are the datasources and the mappers.
Then create another Mybatis config file (with its own datesource and mappers) and dynamically choose the file to build the session factory. You can still provide the connection when opening the session, although I recommend using the implicit one provided by the factory because it will match with the mapper. (Unless this is a complex application where you need to reuse the connection, e.g: to complete a transaction)

Web application with one schema per User

I am trying to enable my web application to use one (MySQL) schema per user.
I am using Spring with JPA along with Hibernate.
Is the Hibernate Multi-tenancy concept relevant?
The way I am trying to do it is
(a) have a EntityManagerFactory per HTTPSession and
(b) set the schema in it at login.
I have figured out how to do (b), but I still have issues doing (a).
I tried putting #Scope(WebApplicationContext.SCOPE_SESSION), but what about the global EntityManagerFactory?
Any help?
You can implement your own ConnectionProvider and there make extra settings.
But I think that you have large problems with the architecture your application if you want to do one schema per user.
UPD1
If you use spring. You can try to declare a bean with own impl of ConnectionProvider in Session scope.
But there is a big problem. Hibernate make the ConnectionProvider. It means that you have to impl own ServiceRegistry (with working through Spring) and override StandardServiceRegistryBuilder, and impl EntityManagerFactoryBuilder (based on EntityManagerFactoryBuilderImpl but with your StandardServiceRegistryBuilder).
When new session have been created it'll use ConnectionProvider to create the connection (Probably you'll have to override some classes).
This is really not suggested.. This will harm you later, you can't do differnt schema for diffrent user. You can always create you own properties to the connection..
Configuration cfg = new Configuration();
cfg.configure();
System.setProperty("hibernate.connection.password",pass);
System.setProperty("hibernate.connection.username",usr);
System.setProperty("hibernate.connection.driver_class", driver_class);
System.setProperty("hibernate.connection.url", driver_url);
System.setProperty("hibernate.dialect", dialect);
// etc, etc, for all properties
cfg.setProperties(System.getProperties());
sessionFactory = cfg.buildSessionFactory();
It can be something like that.. But this is WRONG!

set bootPassword for derby database at runtime using hibernate

I use Hibernate and Derby.
I have a hibernate.cfg.xml and all I did for working with db waas to get a Session :
return new AnnotationConfiguration().configure( "files/hibernate.cfg.xml" ).buildSessionFactory().getCurrentSession();
my hibernate.cfg.xml containes
<property name="connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property>
<property name="connection.url">jdbc:derby:crmdb;create=true</property>
and some other properties and mappings for entity classes.
now I want to set dataEncryption for derby db and bootPassword at runtime.
I changed hibernate.cfg.xml :
<property name="connection.url">jdbc:derby:crmdb;create=true;dataEncryption=true;bootPassword=myPass</property>
and everything was ok.
Now I want to set bootPassword at runtime, e.x.by reading from an environment variable. that´s the problem!
when I delete "connection.url" from hibernate.cfg.xml and trying to set it inside my code, this error ocurres :
java.lang.UnsupportedOperationException: The application must supply JDBC connections
and if I delete only bootPassword, it can not connect to db.
any idea ?
It resolved !
I should set "hibernate.connection.url" instead of "connection.url" !
You need to modify the configuration before building the sessionFactory:
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory(){
if(sessionFactory==null){
Configuration configuration = new AnnotationConfiguration().configure( "files/hibernate.cfg.xml" );
configuration.setProperty("hibernate.connection.url", "jdbc:derby:crmdb;create=true;dataEncryption=true;bootPassword="+password);
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
}
return sessionFactory;
}
Other remark : you must avoid to recreate a new SessionFactory everytime (it take a lot of time, consume lot of resources and it's useless). i.e. You must create one sessionFactory for each bootPassword (since it's the only dynamic part) and if you only have one bootPassword - i.e. one single DB - then your sessionFactory can/must be a singleton.
ref

Can I use an existing Hibernate SessionFactory to reinitialize my database schema?

I'd like to provide the ability to completely wipe my webapp's database from its GUI, rebuilding the tables with the auto-generated DDL gleaned from an AnnotationConfiguration.
At the moment I do this by programatically setting hibernate.hbm2ddl.auto to create and then creating a new SessionFactory.
AnnotationConfiguration cfg = new AnnotationConfiguration();
if (nukeDB)
cfg.setProperty("hibernate.hbm2ddl.auto", "create");
for (Class<?> clas : HibernateMappedClasses) {
cfg.addAnnotatedClass(clas);
}
return cfg.buildSessionFactory();
but this requires creating a fresh AnnotationConfiguration from the one that Spring is building for the rest of the app.
Can I use my existing SessionFactory to recreate the database schema?
This isn't simple in raw Hibernate, but given that I'm using Spring, it turns out that the LocalSessionFactoryBean has methods dropDatabaseSchema and createDatabaseSchema that together do the trick.
Without Spring I think I'd copy the code in those methods!

Hibernate: overriding xml config file with another file

I have a source tree composed of source and test classes. When I run the tests, I'd like to use <property name="hbm2ddl.auto">create</property> while when running the code I'd like to use a validate value instead of create.
I thought to use two config files, one with all the properties and containing hbm2ddl.auto set to validate, and another with hbm2ddl.auto set to create. I hoped that the following code would have allowed me to read from the tests the basic file and override the only hbm2ddl.auto propery, but it doesn't work (the value of hbm2ddl.auto is still the one read from hibernate.cfg.xml.
Configuration configuration = new Configuration();
configuration = configuration.
configure("hibernate.cfg.xml").
addResource("hibernate-test.cfg.xml");
How can I have two different values for a property, without replicating the whole config file?
It seems to me that when you have only a few values to override, one simple approach is to load the xml config as usual, and then call setProperty programmatically, like this:
Configuration configuration = new Configuration();
configuration = configuration.configure("hibernate.cfg.xml");
configuration.setProperty("hibernate.hbm2ddl.auto", "create-drop");
hbm.xml files don't allow to override values with addResource(...) as I tried to do, the values are only added and not overridden
I had that problem with trying to programmatically load another config. Work around i used was to have another hibernate.properties file (instead of xml config). You can set the alternate hibm2ddl value in this properties file and load it using following code:
Properties props = new Properties();
props.load(new FileInputStream(propFile));
configuration = new Configuration().setProperties(props);
Try and see if this works for you.
Imp: don't call configuration.configure().

Categories