Dynamically selecting data sources in Spring Hibernate - approaches - java

Is there a simple way to Choose the datasource by reading from UI or a properties file using Spring and Hibernate, if for eg. the Datasources are X and Y. ?
One approach would be to have dual configuration of sessionfactory, datasource and transaction manager. Then, based on the selection of datasource, the DAO is injected with the appropriate sessionfactory. Is there a better option?
My scenario is that I should be able to switch between two databases on the fly as and when client requires a change in DB for the same application.
Is it a good approach to have DAO with DB compatible methods for eg. a method to retrieve data from DB X and another method to retrieve Data from DB Y as data retrieval varies from one DB to another and calling the methods dynamically at run-time.
or
Is it a better approach to have different versions of same application altogether for X and Y databases for the sake of Database compatibility with java ? If this is the right approach I would like to understand why ?

In addition to Spring profiles you can also consider Spring's AbstractRoutingDataSource
The general idea is that a routing DataSource acts as an intermediary
- while the ‘real’ DataSource can be determined dynamically at runtime based upon a lookup key.
You can find more info in this blog and a somewhat newer post, giving an exemplary use with hibernate.
The AbstractRoutingDataSource is easy to use and will support your scenario where you need to switch the DBs on the fly based on some parameter. The later post gives you an example where the switch is made on the fly based on the user selected locale

I have used option one with success: property file, people can change it even by themselves. If you manage to make two implementations of a Dao interface that behave in the same way then go for it, I don't see any reason to do two different applications.
Define config.dao.id with value daoOracle or daoMySql
<bean id='daoOracle' abstract='true' class='...'/>
<bean id='daoMySql' abstract='true' class='...'/>
<bean id='dao' parent='${config.dao.id}'/>
<bean id='myService' class='...'>
<property name='dao' ref='dao'>
</bean>

Related

How to map custom data structures to bean entities with JPA/Hibernate?

We have a (possibly large) custom data structure implemented in Java (8+). It has a simple and optimal API for querying pieces of data. The logical structure is roughly similar to an RDMS (it has e. g. relations, columns, primary keys, and foreign keys), but there is no SQL driver.
The main goal is to access the data via ORM (mapping logical entities to JPA annotated beans). It would be nice if we could use JPQL. Hibernate is preferred but other alternatives are welcome too.
What is the simplest way to achieve this? Which are the key parts of such an implementation?
(P. S. Directly implementing SessionImplementor, EntityManagerImplementor etc. seems to be too complicated.)
You have two possibilities.
Implement a JDBC compliant driver for your system, so you can use a JPA implementation such as Hibernate "directly" (although you may need to create a custom dialect for your system).
Program directly against the JPA specification like ObjectDB does, which bypasses the need to go through SQL and JPA implementations completely.
The latter one is probably easier, but you'd still need to implement the full JPA API. If it's a custom in-house-only system, there's very little sense in doing either one.
One idea I thought up just now, that I feel may work is this:
Use an existing database implementation like H2 and use the JPA integration with that. H2 already has a JPA integration libraries, so it should be easy.
In this database, create a Java stored procedure or function and call it from your current application through JPA. See this H2 documentation on how to create a Java stored procedure or function. (You may want to explore the section "Using a Function as a Table" also.)
Define a protocol for the service methods and encapsulate it in a model class. An instance of this model class may be passed to the function/SP and responses retrieved.
Caveat: I have never done this myself but I think it will work.
Edit: Here is a diagram representing the thought. Though the diagram show H2 separately, it will most probably be in the same JVM as "Your Java/JEE application". However, since it is not necessary to use H2, I have shown it as as separate entity.

How to use multiple data-source (one for read and another for write) within a single transaction in Spring?

I have configured two databases. One for read (Read-Only), other for Read-Write operations. I have service which involves both read and write operations. I would like to use the read-only db for all read operations and the other db for write operations. How could I achieve this with Spring transactions. I've implemented annotation based approach which changes the datasource using AbstractRoutingDataSource. But, everytime I need to create a new transation using propogation=Requires_New. Is there a better way to do this?
#DbSource(DbType.READ_REPLICA)
#Transactional(propogation=Requires_New)
public Object readData(long id) {
return dataDao.find(id);
}
You should create seperate spring configurations for both of your datastores together with TransactionManager beans. At least one of these beans should have name value so you can use proper transactional manager when needed:
#Transactional(transactionManager="DS1transactionManagerBeanName")
// DS1dataStoreRelevant class/method
Of course combining logic which uses both data stores in single transaction is not possible with JpaTransactionManager. If this is what you are looking for you should consider using distributed JtaTransactionManager provided by web container like IBM WebSphere or other like Atomikos/Bitronix etc. which provides you with transactionality between different data stores (XA resources in general).
Some possible workaround in certain cases (like Oracle datastores) would be to provide visibility from one database to other and use single data store/transaction manager but I am not entirely sure how it works underneath on the database side.
The most basic solution would be just to not mix logic impacting each of the data store and arrange it in sequential transactions but as said whole chain of operations won't be transnational itself so possible rollback would apply only to current transaction (no rollback to the ones committed earlier). It would require some extra logic to introduce rollback/retry policy with dirty flags etc.

Design pattern involving interaction between multiple datasources

I have always used the DAO pattern for CRUD operations, each DAO in charge of accessing to a unique datasource at a time, and use generics to support multiple entities.
Now I require the same with the following changes
1.- Datasources will be added/removed dynamically at runtime
2.- A unit of work involve for instance: reading from datasource A, writing on B and deleting from A if B succeded. A and B will be interchangeable, which makes me think of some sort of origin/destination mechanism.
3.- Reads will only be done against 1 datasource only
The entities will be the same in all datasource, for which I could add a factory that creates a new DAO whenever a datasource is added, answering the first question. But I'm not sure how to address the rest.
Is the DAO pattern still suitable? If it is, what needs to be added? Or is there a different approach to this as a whole?
If Spring is part of your application stack, You can use AbstractRoutingDataSource which will give the flexibility to add dynamic datasource mapping. If not go through the source code of it and you can build your own logic something similar to this.
On a quick google, I come across this http://blog.springsource.org/2007/01/23/dynamic-datasource-routing/.
It is explaining this dynamic routing in action.
This sounds like a business transaction. You need a business component covering the transaction, which involves multiple DAOs.

About Data Objects and DAO Design when using Hibernate

I'm hesitating between two designs of a database project using Hibernate.
Design #1.
(1) Create a general data provider interface, including a set of DAO interfaces and general data container classes. It hides the underneath implementation. A data provider implementation could access data in database, or an XML file, or a service, or something else. The user of a data provider does not to know about it.
(2) Create a database library with Hibernate. This library implements the data provider interface in (1).
The bad thing about Design #1 is that in order to hide the implementation details, I need to create two sets of data container classes. One in the general data provider interface - let's call them DPI-Objects, the other set is used in the database library, exclusively for entity/attribute mapping in Hibernate - let's call them H-Objects. In the DAO implementation, I need to read data from database to create H-Objects (via Hibernate) and then convert H-Objects into DPI-Objects.
Design #2.
Do not create a general data provider interface. Expose H-Objects directly to components that use the database lib. So the user of the database library needs to be aware of Hibernate.
I like design #1 more, but I don't want to create two sets of data container classes. Is that the right way to hide H-Objects and other Hibernate implementation details from the user who uses the database-based data provider?
Are there any drawbacks of Design #2? I will not implement other data provider in the new future, so should I just forget about the data provider interface and use Design #2?
What do you think about this? Thanks for your time!
Hibernate Domain objects are simple POJO so you won't have to create separate DPI-objects, H-Object themselves can be used directly. In DAO you can control whether they come from hibernate or anything else.
I highly recommend reading Chapter 4 "Hitting the database" of Spring in Action, 3rd edition, even if you aren't using Spring in your application. Although my second recommendation would be to use Spring :-)
The DAO pattern is a great way to keep database and ORM logic isolated in the DAO implementation, and you only need one set of entity objects. You can make that happen without Spring, it just takes more work managing your sessions and transactions.
If I understand your post, this is sort of a middle-ground between Design 1 and Design 2. The H-Objects (the entities that Hibernates loads and persists) don't need any Hibernate specific code in them at all. That makes them perfectly acceptable to be used as your DPI-Objects.
I've had arguments with folks in the past who complain that the use of JPA or Hibernate Annotations exposes Hibernate specifics through the DAO interface. I personally take a more pragmatic view, since annotations are just metadata, and don't directly affect the operation of your entity classes.
If you do feel that the annotations expose too much, then you can go old school and use Hibernate Mappings instead. Then your H-Objects are 100% Hibernate free :-)
I recommend design #2. Simply construct domain objects, and let hibernate look after them. Don't write separate classes that are persisted.
Hibernate tries to hide most of the persistence business from you. You may need to add a few small annotations to your entities to help it along. But certainly don't make separate classes.
You may need some very small DAO classes. For example, if you have a Person entity, it would be fairly common practice to have a PersonDAO object that saves a person. Having said that, the code inside the DAO will be very simple, so for a really small project, it may not be worth it. For a large project, it's probably worth keeping your persistence code separate from your business logic, in case you want to use a different persistence technology later.

Multiple transaction managers in spring and select one at runtime

For each client, I have separate databases but business logic and tables are same for each client. I want common service and dao layer for each client. In dao, I select datasource based on logged user client. In #Transactional, I have to pass bean id of transaction manager. How to make common service layer with #Transactional annotation.
Same question is here
Multiple transaction managers - Selecting a one at runtime - Spring
Choose between muliple transaction managers at runtime
but nobody reply
If you want to create a database connection dynamically, then have a look at this SO post.
From the post linked : Basically in JDBC most of these properties are not configurable in the
API like that, rather they depend on implementation. The way JDBC
handles this is by allowing the connection URL to be different per
vendor.
So what you do is register the driver so that the JDBC system can know
what to do with the URL:
DriverManager.registerDriver((Driver)
Class.forName("com.mysql.jdbc.Driver").newInstance());
Then you form
the URL:
String url =
"jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]"
And finally, use it to get a connection:
Connection c = DriverManager.getConnection(url);
In more
sophisticated JDBC, you get involved with connection pools and the
like, and application servers often have their own way of registering
drivers in JNDI and you look up a DataSource from there, and call
getConnection on it.
In terms of what properties MySQL supports, see here (The link is dead).
EDIT: One more thought, technically just having a line of code which
does Class.forName("com.mysql.jdbc.Driver") should be enough, as the
class should have its own static initializer which registers a
version, but sometimes a JDBC driver doesn't, so if you aren't sure,
there is little harm in registering a second one, it just creates a
duplicate object in memeory.
I don't know if this will work, since I have not tested it, but you
could try.
Now what you could do is, use the #Transactional annotation on top of the DAOs without specifying any values (That works). Now in your DAO classes, instead of injecting any DataSource bean, create your own dataSource dynamically as specified in the above link and then either inject that dependency at runtime, use getter setter methods, or just use the new keyword. I hope that'd do the trick.
NOTE: I have not tested it myself yet, so if this works, do let me know.
You do not need to configure and switch between multiple transaction managers to accomplish your end goal. Instead use the Spring provided org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource mechanism.
Detailed examples can be found here :
https://spring.io/blog/2007/01/23/dynamic-datasource-routing/
http://howtodoinjava.com/spring/spring-orm/spring-3-2-5-abstractroutingdatasource-example/

Categories