本文通過一個最精簡的「教師信息管理」案例,手把手演示 Hibernate 核心配置、映射文件編寫、SessionFactory 構建、事務管理與基本增刪改查操作,適合初學者快速跑通第一個 Hibernate 程序。
test schemapublic class Teacher {
private String username; // 主鍵
private String password;
private int age;
// getter/setter 省略
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.domain">
<class name="Teacher" table="Teacher">
<id name="username" type="java.lang.String" column="username">
<generator class="assigned"/> <!-- 主鍵手動分配 -->
</id>
<property name="password" column="password" length="50"/>
<property name="age" column="age" length="10"/>
</class>
</hibernate-mapping>
關鍵點:generator class="assigned" 表示主鍵非自增,由應用層賦值;name 對應實體屬性,column 對應表欄位。
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"https://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 數據庫連接 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="hibernate.connection.password">your_password</property>
<!-- 映射文件註冊 -->
<mapping resource="com/hibernate/domain/Teacher.hbm.xml"/>
</session-factory>
</hibernate-configuration>
public class TeacherDao {
private static final SessionFactory sf = new Configuration().configure().buildSessionFactory();
// 通用事務模板
private void execute(HibernateCallback callback) {
Session session = null;
Transaction tx = null;
try {
session = sf.openSession();
tx = session.beginTransaction();
callback.doInSession(session);
tx.commit();
} catch (Exception e) {
if (tx != null) tx.rollback();
throw new RuntimeException(e);
} finally {
if (session != null) session.close();
}
}
// 插入
public void insert(Teacher teacher) {
execute(session -> session.save(teacher));
}
// HQL 查詢
public List<Teacher> find(String hql) {
List<Teacher> result = new ArrayList<>();
execute(session -> {
Query query = session.createQuery(hql);
result.addAll(query.list());
});
return result;
}
@FunctionalInterface
interface HibernateCallback {
void doInSession(Session session);
}
}
設計亮點:使用函數式接口 + Lambda(JDK 8+)消除樣板代碼,統一事務邊界與資源釋放。
public class Test {
public static void main(String[] args) {
TeacherDao dao = new TeacherDao();
// 1. 插入
Teacher t = new Teacher();
t.setUsername("username4");
t.setPassword("root4");
t.setAge(20);
dao.insert(t);
// 2. 查詢
List<Teacher> list = dao.find("from Teacher");
list.forEach(teacher -> System.out.println(teacher.getUsername()));
}
}
| 問題 | 解決方案 |
|---|---|
| 映射文件找不到 | 確保 .hbm.xml 與實體類同包,且 cfg.xml 中 resource 路徑為 classpath 相對路徑(用 / 分隔) |
| 表不存在 | 先在數據庫手動建表,或啟用 hibernate.hbm2ddl.auto=update 自動建表(僅開發環境) |
| 主鍵衝突 | assigned 模式下確保 username 唯一,或改用 identity/native 自增策略 |
| 事務未提交 | Hibernate **必須在事務中**執行增刪改,查詢建議也加事務保證隔離級別 |
| Session 重複打開 | 嚴格遵循「一請求一 Session」模式,使用 ThreadLocal 或 Spring 管理 |
跑通此流程,你已掌握 Hibernate **配置 → 映射 → SessionFactory → Session → 事務 → CRUD** 核心鏈路。下一步建議學習:
Hibernate 雖屬「老牌」框架,但其 ORM 思想、Session 管理、快取機制、併發控制仍是現代持久層技術的基石,深入理解極具價值。