首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate 3.x 呼叫預存程序完全指南:從映射配置到四大操作實戰

     編輯:Java 相關知識

Hibernate 3.x 提供多種方式呼叫資料庫預存程序。本文以 MySQL 為例,完整示範從 hbm.xml 映射配置查詢類預存程序,到透過 Session 取得 JDBC Connection 呼叫增/刪/改類預存程序的完整實作流程。

環境與準備

  • Hibernate 3.0
  • MySQL 資料庫 (需支援預存程序,5.0+)
  • 測試表 tbl_user (userid, name, blog)

1. Hibernate 核心配置 (hibernate.cfg.xml)

<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<mapping resource="com/amigo/proc/model/User.hbm.xml"/>

2. 實體類與映射檔 (User.hbm.xml) - 關鍵:sql-query 配置查詢類 SP

User.java

public class User implements java.io.Serializable {
    private String userid;
    private String name;
    private String blog;
    // getter/setter 省略
}

User.hbm.xml - 重點在 <sql-query> 區塊

<hibernate-mapping package="com.amigo.proc.model">
  <class name="User" table="tbl_user">
    <id name="userid" column="userid">
      <generator class="assigned"/>
    </id>
    <property name="name" column="name" type="string"/>
    <property name="blog" column="blog" type="string"/>
  </class>

  <!-- 定義呼叫查詢類預存程序 getUserList() -->
  <sql-query name="getUserList" callable="true">
    <return alias="user" class="User">
      <return-property name="userid" column="userid"/>
      <return-property name="name" column="name"/>
      <return-property name="blog" column="blog"/>
    </return>
    {call getUserList()}
  </sql-query>
</hibernate-mapping>

關鍵屬性說明:

  • callable="true":宣告這是預存程序呼叫
  • <return>:定義結果集映射到實體
  • alias:結果集別名,供 return-property 參考
  • {call getUserList()}:JDBC Escape 語法呼叫預存程序

3. 測試類:四大操作完整實作 (ProcTest.java)

public class ProcTest {
    public static void main(String[] args) throws Exception {
        ProcTest proc = new ProcTest();
        Session session = HibernateSessionFactory.getSession();

        proc.testProcQuery(session);   // 查詢
        proc.testProcUpdate(session);  // 更新
        System.out.println("update successfully");
        proc.testProcInsert(session);  // 新增
        System.out.println("insert successfully");
        proc.testProcDelete(session);  // 刪除
        System.out.println("delete successfully");
        session.close();
    }

    // 1. 查詢類:使用映射檔定義的 named query
    private void testProcQuery(Session session) throws Exception {
        List list = session.getNamedQuery("getUserList").list();
        for (int i = 0; i < list.size(); i++) {
            User user = (User) list.get(i);
            System.out.print("序號: " + (i+1));
            System.out.print(", userid: " + user.getUserid());
            System.out.print(", name: " + user.getName());
            System.out.println(", blog: " + user.getBlog());
        }
    }

    // 2. 更新類:透過 JDBC CallableStatement
    private void testProcUpdate(Session session) throws Exception {
        Transaction tx = session.beginTransaction();
        Connection con = session.connection();  // 取得底層 JDBC Connection
        String procedure = "{call updateUser(?, ?, ?)}";
        CallableStatement cstmt = con.prepareCall(procedure);
        cstmt.setString(1, "陳xx");
        cstmt.setString(2, "https://www.blogjava.net/sterningChen");
        cstmt.setString(3, "sterning");
        cstmt.executeUpdate();
        tx.commit();
    }

    // 3. 新增類:同樣透過 Connection + CallableStatement
    private void testProcInsert(Session session) throws Exception {
        session.beginTransaction();
        // 注意:此處使用 PreparedStatement 也可呼叫預存程序 (MySQL 支援)
        PreparedStatement st = session.connection().prepareStatement("{call createUser(?, ?, ?)}");
        st.setString(1, "amigo");
        st.setString(2, "阿蜜果");
        st.setString(3, "https://www.wblogjava.net/amigoxie");
        st.execute();
        session.getTransaction().commit();
    }

    // 4. 刪除類
    private void testProcDelete(Session session) throws Exception {
        session.beginTransaction();
        PreparedStatement st = session.connection().prepareStatement("{call deleteUser(?)}");
        st.setString(1, "amigo");
        st.execute();
        session.getTransaction().commit();
    }
}

核心技術點總結

兩種呼叫模式

模式適用場景實作方式
映射檔 sql-query查詢類預存程序 (需結果集映射實體)<sql-query name="..." callable="true"> + session.getNamedQuery()
JDBC Connection增/刪/改類、複雜參數、需交易控制session.connection() → CallableStatement/PreparedStatement

關鍵 API

  • Session.getNamedQuery(String):取得映射檔定義的命名查詢
  • Session.connection():取得底層 JDBC Connection (Hibernate 3.x 仍支援,4.x+ 建議用 session.doWork() 或 session.doReturningWork())
  • Connection.prepareCall(String):建立 CallableStatement 呼叫預存程序
  • {call proc_name(?,?)}:JDBC Escape 語法,跨資料庫可攜

交易管理

增/刪/改操作必須在交易中進行:session.beginTransaction() → 操作 → tx.commit()。查詢類若無修改可不開交易 (但建議統一管理)。

總結

Hibernate 3.x 透過 hbm.xml 的 sql-query 優雅解決查詢類預存程序映射,並保留 Session.connection() 回溯 JDBC 原生呼叫能力,兼顧 ORM 抽象與底層控制。實務上建議:

  1. 查詢類 SP 盡量用 sql-query 映射,享受自動結果集映射
  2. 非查詢類 SP 用 CallableStatement,參數綁定型別安全
  3. 統一交易邊界,避免資料不一致
  4. 注意 Hibernate 4.x+ session.connection() 已棄用,遷移時需調整
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved