com.microsoft.jdbc.sqlserver.SQLServerDriver)MyEclipse 向導讀取資料庫元數據,自動生成:
hibernate.cfg.xml (SessionFactory 配置)*.hbm.xml 映射文件AbstractXxx (含所有屬性 Getter/Setter) + 具體實體類 Xxx extends AbstractXxx (供開發者擴展業務方法,不被重複覆蓋)<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 2.0//EN"
"https://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.username">sa</property>
<property name="connection.url">jdbc:microsoft:sqlserver://localhost:1433;databaseName=RMSDB</property>
<property name="dialect">net.sf.hibernate.dialect.SQLServerDialect</property>
<property name="connection.password">jckjdkmcj</property>
<property name="connection.driver_class">com.microsoft.jdbc.sqlserver.SQLServerDriver</property>
<mapping resource="zy/pro/hrms/dao/Staffs.hbm.xml"/>
<mapping resource="zy/pro/hrms/dao/Houses.hbm.xml"/>
<mapping resource="zy/pro/hrms/dao/Menus.hbm.xml"/>
<mapping resource="zy/pro/hrms/dao/Tables.hbm.xml"/>
<mapping resource="zy/pro/hrms/dao/Customers.hbm.xml"/>
<mapping resource="zy/pro/hrms/dao/Notice.hbm.xml"/>
</session-factory>
</hibernate-configuration>
關鍵點:方言 SQLServerDialect、驅動類、連接 URL、映射資源註冊。密碼明文存儲僅限開發環境,生產必須外部化 (JNDI DataSource / 加密配置)。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"https://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping package="zy.pro.hrms.dao">
<class name="Houses" table="Houses">
<id name="hid" column="HID" type="java.lang.Integer">
<generator class="increment"/> <!-- 對應上篇策略 -->
</id>
<property name="alias" column="alias" type="java.lang.String"/>
<property name="description" column="description" type="java.lang.String"/>
<property name="capity" column="capity" type="java.lang.Integer" not-null="true"/>
</class>
</hibernate-mapping>
映射細節:package 屬性簡化類名;id 映射主鍵,generator class="increment" 由 Hibernate 內存計數器生成;not-null="true" 映射資料庫約束,Hibernate 運行時校驗。
// 抽象基類 (工具生成,勿手動修改)
public abstract class AbstractHouses {
private Integer hid;
private String alias;
private String description;
private Integer capity;
// 全屬性 Getter/Setter...
public AbstractHouses() {}
public AbstractHouses(Integer hid) { this.hid = hid; }
}
// 具體實體類 (開發者擴展業務邏輯,永不重複生成覆蓋)
public class Houses extends AbstractHouses implements Serializable {
public Houses() {}
public Houses(Integer hid) { super(hid); }
// 可添加業務方法、驗證邏輯、toString 等
}
此設計體現 「生成代碼與業務代碼分離」 原則,是早期代碼生成器的最佳實踐,現代 JPA 註解直接標注在實體類上達成同樣目標。
package zy.pro.hrms.test;
import net.sf.hibernate.Session;
import net.sf.hibernate.Transaction;
import zy.pro.hrms.util.HibernateSessionFactory; // 工具類:ThreadLocal 綁定 Session
import zy.pro.hrms.dao.*;
public class HouseTest {
public static void main(String[] args) {
try {
Session session = HibernateSessionFactory.currentSession();
Transaction tx = session.beginTransaction();
for (int i = 0; i < 50; i++) {
Houses h = new Houses();
// h.setHid(new Integer(2)); // 若手動設置 ID,increment 策略可能衝突
h.setAlias("dddd");
h.setCapity(new Integer(4));
session.save(h);
// tx.commit(); // 注意:此處在循環內提交,每條獨立事務
}
tx.commit(); // 若移至循環外,則 50 條同一事務,性能更好
} catch (Exception e) {
e.printStackTrace();
} finally {
HibernateSessionFactory.closeSession(); // 關鍵:釋放 ThreadLocal Session
}
}
}
| 位置 | 行為 | 性能 | 一致性 |
|---|---|---|---|
循環內 tx.commit() | 每條 save 獨立事務,自動 flush | 低 (50 次提交開銷) | 單條失敗不影響其他 |
循環外 tx.commit() (推薦) | 批次緩存,一次 flush + 一次提交 | 高 (JDBC 批次優化) | 全成功或全回滾,需業務允許 |
原文註釋「粗體內容放的位置不同對程序有什麼影響」,即指此事務邊界選擇。生產環境批次操作必須循環外提交,並配置 hibernate.jdbc.batch_size 發揮最大吞吐。
increment 生成 (1,2,3...),資料庫無 IDENTITY 干擾。@Entity @Table(name="Houses")
public class House {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) // 或 SEQUENCE
private Integer hid;
private String alias;
private String description;
private Integer capity;
// Getter/Setter...
}
@Repository
public interface HouseRepository extends JpaRepository {}
@Service @Transactional
public class HouseService {
@Autowired HouseRepository repo;
public void batchInsert() {
List list = IntStream.range(0, 50)
.mapToObj(i -> { House h=new House(); h.setAlias("dddd"); h.setCapity(4); return h; })
.collect(Collectors.toList());
repo.saveAll(list); // 自動批次、事務管理
}
}
時代變了,但「主鍵策略配置、事務邊界控制、批次優化」的核心知識永遠有效。