Hibernate.orgCommunity Documentation
You may also express queries in the native SQL dialect of your database. This is useful if you want to utilize database specific features such as query hints or the CONNECT BY option in Oracle. It also provides a clean migration path from a direct SQL/JDBC based application to Hibernate. Note that Hibernate allows you to specify handwritten SQL (including stored procedures) for all create, update, delete, and load operations (please refer to the reference guide for more information.)
To use a SQL query, you need to describe the SQL resultset, this
description will help the EntityManager
to map your
columns onto entity properties. This is done using the
@SqlResultSetMapping
annotation. Each
@SqlResultSetMapping
has a name which is used when
creating a SQL query on EntityManager
.
@SqlResultSetMapping(name="GetNightAndArea", entities={
@EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
@FieldResult(name="id", column="nid"),
@FieldResult(name="duration", column="night_duration"),
@FieldResult(name="date", column="night_date"),
@FieldResult(name="area", column="area_id")
}),
@EntityResult(name="org.hibernate.test.annotations.query.Area", fields = {
@FieldResult(name="id", column="aid"),
@FieldResult(name="name", column="name")
})
}
)
//or
@SqlResultSetMapping(name="defaultSpaceShip", entities=@EntityResult(name="org.hibernate.test.annotations.query.SpaceShip"))
You can also define scalar results and even mix entity results and scalar results
@SqlResultSetMapping(name="ScalarAndEntities",
entities={
@EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
@FieldResult(name="id", column="nid"),
@FieldResult(name="duration", column="night_duration"),
@FieldResult(name="date", column="night_date"),
@FieldResult(name="area", column="area_id")
}),
@EntityResult(name="org.hibernate.test.annotations.query.Area", fields = {
@FieldResult(name="id", column="aid"),
@FieldResult(name="name", column="name")
})
},
columns={
@ColumnResult(name="durationInSec")
}
)
The SQL query will then have to return a column alias
durationInSec
.
Please refer to the Hibernate Annotations reference guide for more
information about @SqlResultSetMapping.
TODO: This sounds like a dupe...
Now that the result set is described, we are capable of executing
the native SQL query. EntityManager
provides all the
needed APIs. The first method is to use a SQL resultset name to do the
binding, the second one uses the entity default mapping (the column
returned has to have the same names as the one used in the mapping). A
third one (not yet supported by Hibernate entity manager), returns pure
scalar results.
String sqlQuery = "select night.id nid, night.night_duration, night.night_date, area.id aid, "
+ "night.area_id, area.name from Night night, Area area where night.area_id = area.id "
+ "and night.night_duration >= ?";
Query q = entityManager.createNativeQuery(sqlQuery, "GetNightAndArea");
q.setParameter( 1, expectedDuration );
q.getResultList();
This native query returns nights and area based on the
GetNightAndArea
result set.
String sqlQuery = "select * from tbl_spaceship where owner = ?";
Query q = entityManager.createNativeQuery(sqlQuery, SpaceShip.class);
q.setParameter( 1, "Han" );
q.getResultList();
The second version is useful when your SQL query returns one entity reusing the same columns as the ones mapped in metadata.
Native named queries share the same calling API than JP-QL named queries. Your code doesn't need to know the difference between the two. This is very useful for migration from SQL to JP-QL:
Query q = entityManager.createNamedQuery("getSeasonByNativeQuery");
q.setParameter( 1, name );
Season season = (Season) q.getSingleResult();
Copyright © 2005 Red Hat Inc. and the various authors