Hibernate Entity Manager: Result Set Mapping - database

I'm new to Hibernate and I am a fan of iBATIS, but my new work environments forces me to use Hibernate. In the current scenario at my workplace, there are many complex select queries that I feel hibernate doesn't handles very well.
So I thought of writing my own native SQL select queries, with lots and lots of joins and conditions. So far so good.
I'm using the EntityManager to fire the queries and return the result set. The sample code will look like this:
String sqlQuery="select COL_1, COL_2 from MY_TABLE_NAME";
Query q=em.createNativeQuery(sqlQuery,);
List resultList=q.getResultList();
Please keep in mind this is just a code sample. I would like to have a way so that the result set as in this example (COL_1 and COL_2) can be mapped to my JAVA Class that has two (or more) fields.
Also note that this JAVA Class can not be an Entity that is linked to a table, So I need a way to define any of my JAVA class as a resultClass, the way we do in iBATIS.
Is there any way to do it? SO that the I just define a mapping somewhere for any JAVA class and the result set from query gets mapped to my JAVA Class automatically

String sqlQuery="select COL_1, COL_2 from MY_TABLE_NAME";
Query q=em.createNativeQuery(sqlQuery,MY_TABLE_NAME.class);
List<MY_TABLE_NAME> resultList=q.getResultList();
look variable in IDE debug mode, you will get what you want.

Related

Average of difference between two dates using Hibernate JPA in SQL Server

I'm having a table with columns: id, task_type, start_time, end_time. I need to get the Average Time taken by each task. In SQL query I could do:
SELECT task_type, AVG(DATEDIFF(MS, end_time, start_time)) AS average_time GROUP BY task_type
I'm unable to use the DATEDIFF in JPA as it's not supported. If I pass the nativeQury to the JPA "#Query" It shows the column names which are not included in SELECT statement as Invalid, suppose if I pass the aforementioned query as native query I get error the column name id is not valid.
It would be a great help if anyone is able to point out what I'm missing here.
Note: The project is a micro service architecture, database is stored in a Microsoft SQL Server and the API is being written in Spring Boot.
Regarding calling vendor-specific and user-defined functions, see this tutorial on ways you can do that from JPQL.
The function() syntax might not work for you due to the MS parameter (you could probably register a Hibernate user type for that, which is a nuissance). Registering a function in the dialect should work just fine, though. You'll probably want to implement SQLFunction yourself, rather than using the StandardSQLFunction implementation.
As for why the native query doesn't work for you, what is the result class you're trying to map your query onto? Try using an interface or a DTO with the same property names as the aliases used in the query, similar to how you would use projections. If that doesn't work, a result set mapping should.
The way I'd write that in JPQL:
SELECT ent.taskType, AVG( EXTRACT (EPOCH FROM (ent.endTime - ent.startTime)))
FROM Entity ent
GROUP BY ent.taskType
This is the result in seconds, you can manipulate de extract result to whatever you want to show in view.
I solved this by creating the Projection class and JPQL query.

Multimapping in Dapper Without Custom SQL

Is there a way to use multimapping in Dapper in a generic way, without using custom SQL embedded in C# code?
See for example
Correct use of Multimapping in Dapper
Is there a generic way to query the data from 2 related entities, where common fields are determined automatically for join?
Don't do this. Don't even think this way! Databases are long lasting and normalized. Objects are perishable and frequently denormalized, and transitioning between the two is something to do thoughtfully, when you're writing your SQL. This is really not a step to automate. Long, painful experience has convinced many of us that database abstractions (tables and joins) should not just be sucked into (or generated out of) code. If you're not yet convinced, then use an established ORM.
If, on the other hand, you absolutely want to be in control of your SQL, but its the "embedding" in string literals in C# that bugs you, then I couldn't agree more. Can I suggest QueryFirst, a visual studio extension that generates the C# wrapper for your queries. Your SQL stays in a real SQL file, syntax validated, DB references checked, and at each save, QueryFirst generates a wrapper class with Execute() methods, and a POCO for the results.
By multi-mapping, I presume you want to fill a graph of nested objects. A nice way to do this is to use one QueryFirst .sql per class in your graph, then in the partial class of the parent, add a List of children. (QueryFirst generated POCOs are split across 2 partial classes, you control one of them, the tool generates the other.)
So, for a graph of Customers and their orders...
In the parent sql
select * from customers where name like #custName
The child sql
select * from orders where customerId = #customerId
In the parent partial class, for eager loading...
public List<Orders> orders;
public void OnLoad()
{
orders = new getOrders().Execute(customerId); // property of the parent POCO
}
or for lazy loading...
private List<Orders> _orders;
public List<Orders> orders
{
get
{
return _orders ?? _orders = new GetOrders().Execute(customerId);
}
}
5 lines of code, not counting brackets, and you have a nested graph, lazy loaded or eager loaded as you prefer, the interface discoverable in code (intellisense for the input parameter and result). Their might be hundreds of columns in those tables, whose names you will never need to re-type, and whose datatypes are going to flow transparently into your C#.
Clean separation of responsibilities. Total control. Disclaimer : I wrote QueryFirst :-)
Multimapping with Dapper is a method of running multiple SQL queries at once and then return each result mapped to a specific object.
In the context of this question, Multimapping is not even relevant, re: you're asking for a way to automatically generate a SQL query from the given objects and creating the correct joins which would result in a single SQL query which is not related to Multimapping.
I suspect what you're looking for is something along the lines of the Entity Framework. There are a couple of Dapper extension projects you may want to look into which will generate some of your SQL. See: Dapper.Rainbow VS Dapper.Contrib

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:
Create a view that hides the table-less select such as 'create view dtm as select current_timestamp() as datetime'
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
Create a simple stored procedure which only executes 'select current_timestamp()'

Creating database views with NHibernate

Does any one know how to create a view from hibernate with the results of a criteria query?
We've got some legacy parts of our application that use views generated by the app for data retrieval and I like to tie the new NHibernate stuff into those for minimal friction.
I'd turn it into an extension method so I could eventually do stuff like this:
session.CreateCriteria<Thing>().CreateReportView().List();
Any ideas?
The existing process is like this:
SQLString = _bstr_t("SELECT name FROM User WHERE Retired = false");
...run the query process the results, then...
SQLStringView = _bstr_t(" \
BEGIN EXECUTE IMMEDIATE 'CREATE OR REPLACE VIEW ") + ViewName + _bstr_t(" AS ") + SQLString;
So whenever we run this query we get a view that has the same data in it. I can't work out how to replicate this is hibernate though.
To create a view using NHibernate directly, take a look at the 'database-object' mapping element.
Ayende has a good example here.
Check out this article for an explanation of mapping an entity class to a view and a table. I'm not certain that you'll be able to dynamically create your views at runtime as you specified; but perhaps this can be done as part of the schema generation process using the database-object mapping?
If you're only interested in filtering the data being returned, you may want to have a look at Nhibernate's filtering mechanisms; here is a good article outlining their usage.

How to add data to db rows fetched with ZF?

I'm using Zend Framework's Zend_Db_Table classes to fetch data from a database.
I'd like to "refine" each row I fetch from a table by adding something to it. Within a plain old SQL query I would write eg. SELECT *, dueDate<NOW() AS isOverdue. In this example, feeding an extra field to the SQL query would be possible, but sometimes it might be more suitable to do the extra stuff with PHP. Anyway, I'd use this information mainly in my views, eg. to highlight overdue items accordingly.
What would be a good place to add this isOverdue data in a ZF application?
My thoughts so far:
finding that ZF has a built-in mechanism for this (not successful so far)
subclassing Zend_Db_Table_Row
overriding _fetch() in my Zend_Db_Table class
rethinking whether this is a sane pattern at all :)
As a bonus, it would be nice that I could still use ZF to update rows. Maybe this would be (another) reason for a naming convention for custom fields?
Why reinventing the wheel? There's a built in functionality to do this:
$this->select()->from('your_table_name_here', array('*', 'dueDate<NOW() AS isOverdue'));
Simply specify what columns you need using the second parameter of from() function and it will generate the SQL that you need (by default, if you do not use a second parameter it generates "SELECT * FROM table" query).
PavelDubinin.com - Professional Web Development blog

Resources