views:

69

answers:

2

Hi

Our project must be able to run both in Oracle and SQL Server. The problem is we have a number of HQL + native queries with non-standard operators (i.e. bitand and || ) and functions ( i.e. SUBSTR ) that work fine in Oracle but not in SQL Server.

I wonder if Hibernate is capable of translating them dynamically. I suppose that with HQL maybe it does, because it creates an AST but I doubt the same applies with native queries.

Additional question: what's the best approach of dealing with these troublesome queries ? Conditionals, subclassing, others ... the goal is not to modify the code a lot.

Thanx in advance

+1  A: 

I suggest moving the HQL queries from the code to an external .hbm file and to use named queries before switching the Database. The HQL queries shouldn't be a problem as you already said. Native queries are a problem and you have to find the equivalent for the other DBMS. But by putting the queries into the external file you can then configure the sessionfactory to use the database specific .hbm file and do not need to change the code which depends only on the named query which can be a native query or a HQL To get a named Query you can do the foloowing:

Query query = session.getNamedQuery("YourNamedHQLorSQLQuery");
tobsen
You're right, this is a good option for static queries. In fact we have some of them as named queries. But the project is complex and many of the queries are dynamically built ( i.e. http://img69.imageshack.us/img69/7956/20091204175911.png ).
Lluis Martinez
+3  A: 

Use custom Dialects for HQL. Instead of using ||, create your own function called concat. Then, in the SQL Server dialect add this to the constructor:

registerFunction("concat", new VarArgsSQLFunction(Hibernate.STRING, "", "+", ""));

You don't have to change the Oracle dialect because Oracle already has a concat function so it just passes through, but for other functions, you may need to register new functions in both.

For SQL queries, since you're building them dynamically anyway, you could use base class methods, for example super.addBitAndClause(leftSide, rightSide).

You can even get to the dialect dynamically, although Hibernate didn't make it easy by putting on the interface:

Dialect d = ((SessionFactoryImpl)sessionFactory).getDialect()
Brian Deterling
I'll try the registerFunction method, it seems exactly what we need. However I don't quite understand where to put super.addBitAndClause.
Lluis Martinez
In the sample you linked to, you were doing a lot of sql concatenation with if/else statements to do different things for Oracle and SQL Server. I was just saying instead of all the if/else sections, you could have that class extend a base class that has a set of methods to handle differences. You could also use a helper class, for example: String sqlStatement = "select * from table where " + SqlHelper.addBitwideAnd("left, "right")... The base or helper class is then the only class that has to know the dialect differences. That part was only for when you couldn't use HQL.
Brian Deterling
ok now i get it. However i've refactored that code, as we use a decorated Session class to create queries, i replace the specific functions in the SQL query before executing it, with the help of regexp. Not a perfect solution though but it seems to work.
Lluis Martinez