- Hibernate 教程
- Hibernate - 首頁
- ORM - 概述
- Hibernate - 概述
- Hibernate - 架構
- Hibernate - 環境
- Hibernate - 配置
- Hibernate - 會話
- Hibernate - 持久化類
- Hibernate - 對映檔案
- Hibernate - 對映型別
- Hibernate - 示例
- Hibernate - 物件關係對映
- Hibernate - 級聯型別
- Hibernate - 註解
- Hibernate - 查詢語言
- Hibernate - Criteria 查詢
- Hibernate - 原生 SQL
- Hibernate - 快取
- Hibernate - 實體生命週期
- Hibernate - 批次處理
- Hibernate - 攔截器
- Hibernate - ID 生成器
- Hibernate - 儲存圖片
- Hibernate - log4j 整合
- Hibernate - Spring 整合
- Hibernate - Struts 2 整合
- Hibernate - Web 應用
- 對映表示例
- Hibernate - 基於層次結構的表
- Hibernate - 基於具體類的表
- Hibernate - 基於子類的表
- Hibernate 有用資源
- Hibernate - 問題與解答
- Hibernate - 快速指南
- Hibernate - 有用資源
- Hibernate - 討論
Hibernate - 一對一對映
一對一關聯類似於多對一關聯,區別在於該列將被設定為唯一。例如,一個地址物件可以與一個員工物件關聯。
定義 RDBMS 表
考慮這樣一個場景:我們需要將員工記錄儲存在 EMPLOYEE 表中,該表將具有以下結構:
create table EMPLOYEE ( id INT NOT NULL auto_increment, first_name VARCHAR(20) default NULL, last_name VARCHAR(20) default NULL, salary INT default NULL, address INT NOT NULL, PRIMARY KEY (id) );
此外,假設一個地址只能與一個員工關聯,因此可以使用一對一關聯來表示此關聯。我們將把地址相關資訊儲存在具有以下結構的單獨表中:
create table ADDRESS ( id INT NOT NULL auto_increment, street_name VARCHAR(40) default NULL, city_name VARCHAR(40) default NULL, state_name VARCHAR(40) default NULL, zipcode VARCHAR(10) default NULL, PRIMARY KEY (id) );
建立這兩個 RDBMS 表,併為下一步的實現做好準備。
定義 POJO 類
讓我們實現一個 POJO 類**Employee**,它將用於持久化與 EMPLOYEE 表相關的物件,並具有 Address 型別的變數。
import java.util.*;
public class Employee{
private int id;
private String firstName;
private String lastName;
private int salary;
private Address address;
public Employee() {}
public Employee(String fname, String lname, int salary, Address address ) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
this.address = address;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
public Address getAddress() {
return address;
}
public void setAddress( Address address ) {
this.address = address;
}
}
我們需要定義另一個與 ADDRESS 表對應的 POJO 類,以便可以將地址物件儲存到 ADDRESS 表中並從中檢索。
import java.util.*;
public class Address{
private int id;
private String street;
private String city;
private String state;
private String zipcode;
public Address() {}
public Address(String street, String city, String state, String zipcode) {
this.street = street;
this.city = city;
this.state = state;
this.zipcode = zipcode;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet( String street ) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity( String city ) {
this.city = city;
}
public String getState() {
return state;
}
public void setState( String state ) {
this.state = state;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode( String zipcode ) {
this.zipcode = zipcode;
}
}
定義 Hibernate 對映檔案
讓我們開發我們的對映檔案,它指示 Hibernate 如何將定義的類對映到資料庫表。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
<many-to-one name = "address" column = "address" unique="true"
class="Address" not-null="true"/>
</class>
<class name = "Address" table="ADDRESS">
<meta attribute = "class-description">
This class contains the address detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "street" column = "street_name" type = "string"/>
<property name = "city" column = "city_name" type = "string"/>
<property name = "state" column = "state_name" type = "string"/>
<property name = "zipcode" column = "zipcode" type = "string"/>
</class>
</hibernate-mapping>
應將對映文件儲存在格式為
對映文件是一個 XML 文件,其根元素為
,其中包含兩個與每個類對應的 元素。 元素用於定義從 Java 類到資料庫表的特定對映。Java 類名使用 class 元素的 name 屬性指定,資料庫表名使用 table 屬性指定。 元素是可選元素,可用於建立類描述。
元素將類中的唯一 ID 屬性對映到資料庫表的主鍵。id 元素的 name 屬性引用類中的屬性,column 屬性引用資料庫表中的列。type 屬性包含 Hibernate 對映型別,此對映型別將 Java 型別轉換為 SQL 資料型別。 id 元素中的
元素用於自動生成主鍵值。generator 元素的 class 屬性設定為 native,讓 Hibernate 根據底層資料庫的功能選擇 identity、sequence 或 hilo 演算法來建立主鍵。 元素用於將 Java 類屬性對映到資料庫表中的列。元素的 name 屬性引用類中的屬性,column 屬性引用資料庫表中的列。type 屬性包含 Hibernate 對映型別,此對映型別將 Java 型別轉換為 SQL 資料型別。 元素用於設定 EMPLOYEE 和 ADDRESS 實體之間的關係。name 屬性設定為父類中定義的變數,在本例中為 *address*。column 屬性用於設定父表 EMPLOYEE 中的列名,該列名設定為 unique,以便只有一個 Employee 物件可以與一個地址物件關聯。
最後,我們將建立包含 main() 方法的應用程式類來執行應用程式。我們將使用此應用程式儲存一些員工記錄及其證書,然後我們將對這些記錄應用 CRUD 操作。
import java.util.*;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Let us have one address object */
Address address1 = ME.addAddress("Kondapur","Hyderabad","AP","532");
/* Add employee records in the database */
Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, address1);
/* Let us have another address object */
Address address2 = ME.addAddress("Saharanpur","Ambehta","UP","111");
/* Add another employee record in the database */
Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, address2);
/* List down all the employees */
ME.listEmployees();
/* Update employee's salary records */
ME.updateEmployee(empID1, 5000);
/* List down all the employees */
ME.listEmployees();
}
/* Method to add an address record in the database */
public Address addAddress(String street, String city, String state, String zipcode) {
Session session = factory.openSession();
Transaction tx = null;
Integer addressID = null;
Address address = null;
try {
tx = session.beginTransaction();
address = new Address(street, city, state, zipcode);
addressID = (Integer) session.save(address);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return address;
}
/* Method to add an employee record in the database */
public Integer addEmployee(String fname, String lname, int salary, Address address){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary, address);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to list all the employees detail */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
Address add = employee.getAddress();
System.out.println("Address ");
System.out.println("\tStreet: " + add.getStreet());
System.out.println("\tCity: " + add.getCity());
System.out.println("\tState: " + add.getState());
System.out.println("\tZipcode: " + add.getZipcode());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to update salary for an employee */
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
編譯和執行
以下是編譯和執行上述應用程式的步驟。在進行編譯和執行之前,請確保已正確設定 PATH 和 CLASSPATH。
建立 hibernate.cfg.xml 配置檔案,如配置章節中所述。
建立如上所示的 Employee.hbm.xml 對映檔案。
建立如上所示的 Employee.java 原始檔並編譯它。
建立如上所示的 Address.java 原始檔並編譯它。
建立如上所示的 ManageEmployee.java 原始檔並編譯它。
執行 ManageEmployee 二進位制檔案以執行程式。
您將在螢幕上獲得以下結果,同時在 EMPLOYEE 和 ADDRESS 表中建立記錄。
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Manoj Last Name: Kumar Salary: 4000
Address
Street: Kondapur
City: Hyderabad
State: AP
Zipcode: 532
First Name: Dilip Last Name: Kumar Salary: 3000
Address
Street: Saharanpur
City: Ambehta
State: UP
Zipcode: 111
First Name: Manoj Last Name: Kumar Salary: 5000
Address
Street: Kondapur
City: Hyderabad
State: AP
Zipcode: 532
First Name: Dilip Last Name: Kumar Salary: 3000
Address
Street: Saharanpur
City: Ambehta
State: UP
Zipcode: 111
如果您檢查您的 EMPLOYEE 和 ADDRESS 表,它們應該具有以下記錄:
mysql> select * from EMPLOYEE; +----+------------+-----------+--------+---------+ | id | first_name | last_name | salary | address | +----+------------+-----------+--------+---------+ | 7 | Manoj | Kumar | 5000 | 5 | | 8 | Dilip | Kumar | 3000 | 6 | +----+------------+-----------+--------+---------+ 2 rows in set (0.00 sec) mysql> select * from ADDRESS; +----+-------------+-----------+------------+---------+ | id | street_name | city_name | state_name | zipcode | +----+-------------+-----------+------------+---------+ | 5 | Kondapur | Hyderabad | AP | 532 | | 6 | Saharanpur | Ambehta | UP | 111 | +----+-------------+-----------+------------+---------+ 2 rows in set (0.00 sec) mysql>