JPA 規範推薦使用註解將映射元數據與實體類內聚,避免維護雙份文件(Java 類 + .hbm.xml)。本文演示在 Eclipse 中利用 Hibernate Tools 逆向工程,從數據庫表自動生成帶註解的實體類,並完成配置與測試全流程。
以 MySQL 表 commodity 為例:
CREATE TABLE commodity ( Id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), price DOUBLE, unit VARCHAR(50), category VARCHAR(100), description VARCHAR(1000), seller INT );

<?xml version="1.0" encoding="UTF-8"?>
<!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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/zzh</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<!-- 註解實體類掃描 -->
<mapping class="com.zzh.Commodity"/>
</session-factory>
</hibernate-configuration>
關鍵點:<mapping class="..."/>用於註解實體;若用 .hbm.xml 則用resource屬性。
hibernate.reveng.xml 指定目標表:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "https://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd"> <hibernate-reverse-engineering> <table-filter match-catalog="zzh" match-name="commodity"/> </hibernate-reverse-engineering>
Domain code (Java) 與 Generate EJB 3 annotationsGenerate .hbm.xml files

package com.zzh;
import javax.persistence.*;
@Entity
@Table(name = "commodity", catalog = "zzh")
public class Commodity implements java.io.Serializable {
private Integer id;
private String name;
private Double price;
private String unit;
private String category;
private String description;
private Integer seller;
// 無參構造器(Hibernate 必須)
public Commodity() {}
// 全參構造器
public Commodity(String name, Double price, String unit,
String category, String description, Integer seller) {
this.name = name; this.price = price; this.unit = unit;
this.category = category; this.description = description; this.seller = seller;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id", unique = true, nullable = false)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
@Column(name = "name", length = 100)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Column(name = "price", precision = 11)
public Double getPrice() { return price; }
public void setPrice(Double price) { this.price = price; }
@Column(name = "unit", length = 50)
public String getUnit() { return unit; }
public void setUnit(String unit) { this.unit = unit; }
@Column(name = "category", length = 100)
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
@Column(name = "description", length = 1000)
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
@Column(name = "seller")
public Integer getSeller() { return seller; }
public void setSeller(Integer seller) { this.seller = seller; }
}
| 註解 | 作用 |
|---|---|
@Entity | 標識持久化實體類 |
@Table | 指定映射表名、目錄、Schema |
@Id | 聲明主鍵屬性 |
@GeneratedValue | 主鍵生成策略(IDENTITY 自增) |
@Column | 字段映射細節:name、length、nullable、unique、precision 等 |
package com.zzh.utl;
import org.hibernate.*;
import org.hibernate.boot.registry.*;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
Configuration config = new Configuration().configure(); // 讀取 hibernate.cfg.xml
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
.applySettings(config.getProperties());
StandardServiceRegistry registry = builder.build();
sessionFactory = config.buildSessionFactory(registry);
}
public static SessionFactory getSessionFactory() { return sessionFactory; }
public static Session openSession() { return sessionFactory.openSession(); }
public static void closeSession(Session s) { if (s != null) s.close(); }
}
package anno;
import org.hibernate.Query;
import org.hibernate.Session;
import org.junit.*;
import com.zzh.Commodity;
import com.zzh.utl.HibernateUtil;
import java.util.List;
public class ZhuShiTest {
private Session session;
@Before
public void setUp() { session = HibernateUtil.openSession(); }
@After
public void tearDown() { HibernateUtil.closeSession(session); }
@Test
public void testQueryAll() {
String hql = "FROM Commodity";
Query query = session.createQuery(hql);
List<Commodity> list = query.list();
for (Commodity c : list) {
System.out.println("name: " + c.getName());
}
Assert.assertTrue(list.size() > 0);
}
}

早期使用 .hbm.xml 時,<class name="Commodity"> 缺少包名會導致 MappingException: entity not found。修正為 <class name="com.zzh.Commodity"> 即可解決。註解方式將類名與包名綁定在 Java 代碼中,從根本消除此類配置錯誤。


參考教材:《Struts2+Spring3+Hibernate框架技術精講與整合案例》