[Hibernate] Named query

Thông thường, developer hay đặt chuỗi HQL phân tán trong code Java, phương pháp này khó maintaine và trông khá xấu xí. May mắn thay, Hibernate đã đưa ra một kỹ thuật gọi là “names queries”, nó cho phép developer đưa tất cả HQL vào file mapping XML hoặc thông qua annotation.


Cách khai báo named query
Named query hỗ trợ cả HQL hoặc native SQL. xem ví dụ...


1. File XML mapping
HQL trong file mapping
XML:
<!-- stock.hbm.xml -->
<hibernate-mapping>
    <class name="com.mkyong.common.Stock" table="stock" ...>
        <id name="stockId" type="java.lang.Integer">
            <column name="STOCK_ID" />
            <generator class="identity" />
        </id>
        <property name="stockCode" type="string">
            <column name="STOCK_CODE" length="10" not-null="true" unique="true" />
        </property>
        ...
    </class>

    <query name="findStockByStockCode">
        <![CDATA[from Stock s where s.stockCode = :stockCode]]>
    </query>

</hibernate-mapping>
Native SQL trong file mapping
XML:
<!-- stock.hbm.xml -->
<hibernate-mapping>
    <class name="com.mkyong.common.Stock" table="stock" ...>
        <id name="stockId" type="java.lang.Integer">
            <column name="STOCK_ID" />
            <generator class="identity" />
        </id>
        <property name="stockCode" type="string">
            <column name="STOCK_CODE" length="10" not-null="true" unique="true" />
        </property>
        ...
    </class>

    <sql-query name="findStockByStockCodeNativeSQL">
    <return alias="stock" class="com.mkyong.common.Stock"/>
    <![CDATA[select * from stock s where s.stock_code = :stockCode]]>
    </sql-query>
</hibernate-mapping>
Có thể đặt 1 named query trong element ‘hibernate-mapping', nhưng không được đặt trước element ‘class', Hibernate sẽ nhắc nhở khi file mapping không hợp lệ, tất cả các named queries phải đặt sau element ‘class'.

Ghi chú
Về CDATA, nó giúp bọc câu SQL để trình phân tích cú pháp XML sẽ không bị lỗi đối với một số ký tự đặc biệt trong XM như ‘>’ , <‘,...


2. Annotation
HQL trong annotation
Java:
@NamedQueries({
    @NamedQuery(
    name = "findStockByStockCode",
    query = "from Stock s where s.stockCode = :stockCode"
    )
})
@Entity
@Table(name = "stock", catalog = "mkyong")
public class Stock implements java.io.Serializable {
...
Native SQL trong annotation
Java:
@NamedNativeQueries({
    @NamedNativeQuery(
    name = "findStockByStockCodeNativeSQL",
    query = "select * from stock s where s.stock_code = :stockCode",
        resultClass = Stock.class
    )
})
@Entity
@Table(name = "stock", catalog = "mkyong")
public class Stock implements java.io.Serializable {
...
Với native SQL, phải khai báo ‘resultClass' để cho Hibernate biết loại dữ liệu trả về là gì, nếu không sẽ gây ra exception “org.hibernate.cfg.NotYetImplementedException: Pure native scalar queries are not yet supported“.


Gọi named query
Trong Hibernate, có thể gọi named query thông qua phương thức getNamedQuery.

Java:
Query query = session.getNamedQuery("findStockByStockCode")
.setString("stockCode", "7277");
Java:
Query query = session.getNamedQuery("findStockByStockCodeNativeSQL")
.setString("stockCode", "7277");

Kết luận
Phạm vi của named query là global, có nghĩa là tên của query phải là duy nhất trong các file XML mapping hoặc annotation. Trong môi trường thực tế, điều này phải luôn được thực hiện để cô lập tất cả các named query trong file riêng. Ngoài ra, các named query được đưa vào file hibernate mapping hoặc annotation dễ maintain hơn các lệnh SQL nằm rải rác trong code Java.


Cám ơn các bạn đã theo dõi. Hẹn gặp lại các bạn trong các bài viết sau :D

Bài viết tham khảo tại: https://mkyong.com/hibernate/hibernate-named-query-examples/
 

Bình luận