Native SQL

Native SQL statements are also supported in Hibernate, except you will need to use a different API call to compose a query object. There are mainly two reasons you would want to use a native SQL. The first is that you wish to use a specific feature offered by your database solution that may not be supported by Hibernate. The second is when you wish to execute an ad hoc query and store the result in an object that is not a Hibernate entity.

If you don't associate an entity with the query result, Hibernate returns the result set in a list of object array. This is known as a Scalar Query. However, you can associate an entity with the native query and Hibernate will return a list of this entity; this is known as Entity query. Let's see how these work.

Scalar query

When you execute a native SQL, the result of this query is returned in a list of object arrays. Consider the following query:

List<Object[]> objectList = session
.createSQLQuery("SELECT * FROM PERSON")
  .list();

Each element of the list is essentially a row returned from the query. Each element of the object array represents the value of a column.

Hibernate does a good job guessing the scalar data type and will instantiate the appropriate object to hold the value of each column. However, sometimes you may need to specify the type. You can do this by adding a scalar hint for each column you would like to return, as follows:

List<Object[]> objectList = session
.createSQLQuery("SELECT * FROM PERSON")
.addScalar("ID", LongType.INSTANCE)
.addScalar("FIRSTNAME", StringType.INSTANCE)
.addScalar("LASTNAME", StringType.INSTANCE)
.addScalar("BIRTHDATE", DateType.INSTANCE)
.list();

That way, you can safely cast the array elements:

for(Object[] objects: objectList) {
  Long id = (Long) objects[0];
  String firstname = (String) objects[1];
  String lastname = (String) objects[2];
  Date birthdate = (Date) objects[3];
}

Another advantage of adding scalar hints is that it instructs Hibernate to only fetch those columns, so even though you are selecting every column in your native SQL, Hibernate will only extract the values for the columns that are specified. (Please note that the SQL doesn't change, it still is SELECT *, so from a JDBC perspective it fetches all columns.)

Entity query

You can attach an entity to the native SQL and Hibernate will correctly populate this entity for you. The following code demonstrates how this works:

List<Person> persons = session
.createSQLQuery("SELECT * FROM PERSON")
.addEntity(Person.class)
.list();

Hibernate will return the results using the Person class.

It's even possible to join multiple tables and fetch the related entities. For example, you can join the Person table and the Address table to fetch all Persons with their associated Address entities:

String hql = 
    "SELECT p.*, a.* FROM PERSON p, ADDRESS a " + 
    "WHERE p.id = a.person_id";

List<Object[]> objectList = session
    .createSQLQuery(hql)
    .addEntity("p", Person.class)
    .addJoin("a", "p.addresses")
    .list();

It's worth noting a few things in the preceding code. The return type is a list of object arrays, this is because Hibernate will return the Person entity as the first element of Object[], that is, objectList[0], and Address entity as the second element of the array. Also, you may encounter duplicate entities in cases where the association is one to many. If you ever have to fetch the data this way, you may have to carefully extract and handle the root entities and their associated entities using your own code, after you fetch all the data.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.38.121