简体   繁体   中英

How can I call a stored procedure without table names in HQL?

I am trying to fetch the current timestamp through a stored procedure in HQL. This means my code looks something like the following:

var currentTimestamp =
    session.CreateQuery("SELECT CURRENT_TIMESTAMP()")
           .UniqueResult<DateTime>();

This doesn't work. Specifically, it throws a System.NullReferenceException deep inside of the NHibernate HqlParser.cs file. I played around with this a bit, and got the following to work instead:

var currentTimestamp =
    session.CreateQuery("SELECT CURRENT_TIMESTAMP() FROM Contact")
           .SetMaxResults(1)
           .UniqueResult<DateTime>();

Now I have the data I want, but an HQL query I don't. I want the query to represent the question I'm asking -- like my original format.

An obvious question here is "Why are you using HQL?" I know I can easily do with this session.CreateSQLQuery(...) , hitting our MySQL 5.1 database directly. This is simply an example of my core problem, with the root being that I'm using custom parameter-less HQL functions throughout my code base, and I want to have integration tests that run these HQL parameter-less functions in as much isolation as possible.

My hack also has some serious assumptions baked in. It will not return a result, for example, if there are no records in the Contact table, or if the Contact table ceases to exist.

The method to retrieve CURRENT_TIMESTAMP() (or any other database function) outside of the context of a database table varies from database to database - some allow it, some do not. Oracle, for example, does not allow a select without a table, so they provide a system table with a single row which is called DUAL.

I suspect that NHibernate is implementing in HQL primarily features which are common across all database implementations, and thus does not implement a table-less select.

I can suggest three approaches:

  1. Create a view that hides the table-less select such as 'create view dtm as select current_timestamp() as datetime'

  2. Follow the Oracle approach and create a utility table with a single row in it that you can use as the table in a select

  3. Create a simple stored procedure which only executes 'select current_timestamp()'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM