Bạn có thể sử dụng Native SQL trong Hibernate để thực hiện các truy vấn cơ sở dữ liệu nếu bạn muốn sử dụng các tính năng cơ sở dữ liệu cụ thể như hint hoặc từ khoá CONNECT trong Oracle. Hibernate 3.x cho phép bạn chỉ định SQL viết tay, bao gồm các stored procedures, và tất cả các thao tác create, update, delete và select.
Bạn có thể tạo một truy vấn Native SQL từ session với phương thức createSQLQuery() trên interface Session:
public SQLQuery createSQLQuery(String sqlString) throws HibernateException
Nội dung chính
Các kiểu truy vấn Native SQL
Sau khi bạn truyền một chuỗi chứa truy vấn SQL đến phương thức createSQLQuery(), bạn phải liên kết kết quả trả về SQL cho thực thể Hibernate hiện có, một join, hoặc một kết quả vô hướng (scalar) sử dụng các phương thức addEntity(), addJoin() và addScalar() tương ứng.
1. Truy vấn vô hướng (Scalar)
Các truy vấn SQL cơ bản nhất là để có được một danh sách các vô hướng (giá trị) từ một hoặc nhiều bảng. Sau đây là cú pháp để sử dụng SQL gốc cho các giá trị vô hướng:
String sql = "SELECT first_name, salary FROM EMPLOYEE"; SQLQuery query = session.createSQLQuery(sql); query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP); List results = query.list();
2. Truy vấn Entity
Các truy vấn ở trên là về trả về các giá trị vô hướng từ resultset. Sau đây là cú pháp để có được các đối tượng Entity từ một truy vấn Native SQL thông qua addEntity().
String sql = "SELECT * FROM EMPLOYEE"; SQLQuery query = session.createSQLQuery(sql); query.addEntity(Employee.class); List results = query.list();
Truy vấn Entity với Named SQL
Sau đây là cú pháp để nhận các đối tượng thực thể từ truy vấn native sql thông qua addEntity() và sử dụng truy vấn Named SQL.
String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id"; SQLQuery query = session.createSQLQuery(sql); query.addEntity(Employee.class); query.setParameter("employee_id", 10); List results = query.list();
Ví dụ về Native SQL trong Hibernate
Tạo lớp POJO
public class Employee { private int id; private String firstName; private String lastName; private int salary; public Employee() {} public Employee(String fname, String lname, int salary) { this.firstName = fname; this.lastName = lname; this.salary = salary; } public int getId() { return id; } public void setId( int id ) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName( String first_name ) { this.firstName = first_name; } public String getLastName() { return lastName; } public void setLastName( String last_name ) { this.lastName = last_name; } public int getSalary() { return salary; } public void setSalary( int salary ) { this.salary = salary; } }
Tạo bảng EMPLOYEE để lưu trữ các đối tượng Employee
create table EMPLOYEE ( id INT NOT NULL auto_increment, first_name VARCHAR(20) default NULL, last_name VARCHAR(20) default NULL, salary INT default NULL, PRIMARY KEY (id) );
Tạo file mapping Employee.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="Employee" table="EMPLOYEE"> <meta attribute="class-description"> This class contains the employee detail. </meta> <id name="id" type="int" column="id"> <generator class="native"/> </id> <property name="firstName" column="first_name" type="string"/> <property name="lastName" column="last_name" type="string"/> <property name="salary" column="salary" type="int"/> </class> </hibernate-mapping>
Tạo lớp ụng dụng chứa hàm main() để thực hiện các câu truy vấn Native SQL
public class TestNativeSQL { private static SessionFactory factory; public static void main(String[] args) { try { factory = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { System.err.println("Failed to create sessionFactory object." + ex); throw new ExceptionInInitializerError(ex); } TestNativeSQL ME = new TestNativeSQL(); // Add few employee records in database Integer empID1 = ME.addEmployee("Zara", "Ali", 2000); Integer empID2 = ME.addEmployee("Daisy", "Das", 5000); Integer empID3 = ME.addEmployee("John", "Paul", 5000); Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000); // List down employees and their salary using Scalar Query ME.listEmployeesScalar(); // List down complete employees information using Entity Query ME.listEmployeesEntity(); } // Method to CREATE an employee in the database public Integer addEmployee(String fname, String lname, int salary) { Session session = factory.openSession(); Transaction tx = null; Integer employeeID = null; try { tx = session.beginTransaction(); Employee employee = new Employee(fname, lname, salary); employeeID = (Integer) session.save(employee); tx.commit(); } catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return employeeID; } // Method to READ all the employees using Scalar Query public void listEmployeesScalar() { Session session = factory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); String sql = "SELECT first_name, salary FROM EMPLOYEE"; SQLQuery query = session.createSQLQuery(sql); query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP); List data = query.list(); for (Object object : data) { Map row = (Map) object; System.out.print("First Name: " + row.get("first_name")); System.out.println(", Salary: " + row.get("salary")); } tx.commit(); } catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } // Method to READ all the employees using Entity Query public void listEmployeesEntity() { Session session = factory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); String sql = "SELECT * FROM EMPLOYEE"; SQLQuery query = session.createSQLQuery(sql); query.addEntity(Employee.class); List employees = query.list(); for (Iterator iterator = employees.iterator(); iterator.hasNext();) { Employee employee = (Employee) iterator.next(); System.out.print("First Name: " + employee.getFirstName()); System.out.print(" Last Name: " + employee.getLastName()); System.out.println(" Salary: " + employee.getSalary()); } tx.commit(); } catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } }
Kết quả run trên Eclipse
First Name: Zara, Salary: 2000 First Name: Daisy, Salary: 5000 First Name: John, Salary: 5000 First Name: Mohd, Salary: 3000 First Name: Zara Last Name: Ali Salary: 2000 First Name: Daisy Last Name: Das Salary: 5000 First Name: John Last Name: Paul Salary: 5000 First Name: Mohd Last Name: Yasee Salary: 3000