[Hibernate] List 映射例子

List 是 java 集合的一個工具,存儲線性的數據,容許重複數據。開發者能夠準確控制在 list 那個位置插入數據。本例子演示 Java 的 List 集合和 MySQL 數據庫的映射應用。java

使用場景:一個員工有一個或多個證書,對員工以及其擁有的證書進行增刪該查操做。這個一個 1 : n的場景。mysql

代碼的目錄結構以下:sql

hibernate.cfg.xml 存儲數據庫信息,如數據庫類型,帳號密碼,數據庫名稱。數據庫

Empoyee.hbm.xml,聲明 Employee 對象及其屬性和數據庫表結構的對應關係。其中,Employee 的屬性包括一個 Certificate 的 List 集合。後面詳細介紹此文件。session

Employee.java,Employee 實體類。app

Certificate.java, Certificate 實體類。ide

ManageEmployee.java,管理 Employee,並對外提供操做 Employee 對象數據的接口。工具

App.java,演示本例子。ui

 

代碼詳情

EMPLOYEE, CERTIFICATE 在 MySQL 中的建表語句。this

雖然 EMPLOYEE 和 CERTIFICATE 是一對多的關係,在邏輯上 CERTIFICATE.employee_id 指向 EMPLOYEE.id,可是並沒用使用外鍵進行約束,而是經過代碼邏輯進行約束。這樣的結構更靈活些。

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,
   PRIMARY KEY (id)
);

 

create table CERTIFICATE (
   id INT NOT NULL auto_increment,
   certificate_name VARCHAR(30) default NULL,
   idx INT default NULL, 
   employee_id INT default NULL,
   PRIMARY KEY (id)
);

 

Certificate.java 。在數據庫中 CERTIFICATE 有四個屬性,其中 idex 表示證書在 List 中的位置,employee_id 表示歸屬哪個員工,這兩個數據在 Employee.hbm.xml 中聲明,有 hibernate 自動填充。因此,只須要在 Certificate.java 中聲明 id, name 屬性就能夠了。

package tony.hibernateList;

public class Certificate {
    private int id;
    private String name;
    
    public Certificate(){}
    public Certificate(String name){
        this.name = name;
    }
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

Employee.java,除了四個基本類型的屬性外,還有一個集合屬性 List<Certificate> certificates。

package tony.hibernateList;

import java.util.List;

public class Employee {
    private int id;
    private String firstName;
    private String lastName;
    private int salary;
    private List<Certificate> certificates;
    
    public Employee(){}
    public Employee(String fName, String lName, int salary){
        this.firstName = fName;
        this.lastName = lName;
        this.salary = salary;
    }
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    public List<Certificate> getCertificates() {
        return certificates;
    }
    public void setCertificates(List<Certificate> certificates) {
        this.certificates = certificates;
    }
}

 

Employee.hbm.xml,聲明瞭 Employee 類和數據庫 EMPLOYEE 表的映射關係。hbm.xml 雖然做爲 java 對象和數據庫表的中間層,可是和 java 對象類似些。

Class 元素是 java 類和數據庫表的映射關係,其中 name 是 java 的全路徑類名,table 是 MySQL 表名。

id 元素是 java 類中惟一 ID 屬性和數據庫表中主鍵的映射,其中 name 是 java 屬性名稱,column 是數據庫表的列名稱,type 是 hibernate 映射類,用於轉換 java 和 SQL  數據。

property 元素是 java 屬性和數據庫表的列名稱的映射。其中 name, column type 的做用和 id 元素的類似。

list 元素用於聲明 Employee 元素和 Certificate 之間的關係。

  cascade 表示在保存 employee 到數據庫的同時,也要保存其關聯的 certificates 。

  key 聲明指向父類的外鍵。

  list-index 存儲當前證書在其集合中的位置。

  one-to-many 表示這是一對多的狀況。

<?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="tony.hibernateList.Employee" table="EMPLOYEE">
      <id name="id" type="int" column="id">
         <generator class="native"/>
      </id>
      <list name="certificates" cascade="all">
         <key column="employee_id"/>
         <list-index column="idx"/>
         <one-to-many class="tony.hibernateList.Certificate"/>
      </list>
      <property name="firstName" column="first_name" type="string"/>
      <property name="lastName" column="last_name" type="string"/>
      <property name="salary" column="salary" type="int"/>
   </class>

   <class name="tony.hibernateList.Certificate" table="CERTIFICATE">
      <id name="id" type="int" column="id">
         <generator class="native"/>
      </id>
      <property name="name" column="certificate_name" type="string"/>
   </class>

</hibernate-mapping>

 

ManageEmployee.java 是 Employee 及其 Certificate 的操做類。對業務層提供操做 Employee 的接口。僅在 addEmployee 方法作了異常檢測和失敗回滾處理,其餘方法省略,實際代碼應加上。

package tony.hibernateList;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
    
    private static SessionFactory factory;
    
    {
        factory = new Configuration().configure().buildSessionFactory();
    }
    
    /**
     * Add employee and certificate with transaction. Roll back if insert failed
     * @param fname
     * @param lname
     * @param salary
     * @param cert
     * @return
     */
    public Integer addEmployee(String fname, String lname, int salary, List<Certificate> cert){
         Session session = factory.openSession();
          Transaction tx = null;
          Integer employeeID = null;
          try{
             tx = session.beginTransaction();
             Employee employee = new Employee(fname, lname, salary);
             employee.setCertificates(cert);
             employeeID = (Integer)session.save(employee); 
             tx.commit();
          }catch (HibernateException e) {
             if (tx!=null) tx.rollback();
             e.printStackTrace(); 
          }finally {
             session.close(); 
          }
          return employeeID;
    }
    
    public void listEmployee(){
        Session session = factory.openSession();
        Transaction tx = null;
        
        tx = session.beginTransaction();
        List<Employee> emps = session.createQuery("FROM Employee").list();
        for (Employee emp : emps){
            System.out.println(emp.getId() + ", " + emp.getFirstName() + ", " + emp.getLastName() + ", " + emp.getSalary());
            List<Certificate> certs = emp.getCertificates();
            for (Certificate cert : certs){
                System.out.println(cert.getId() + " | " + cert.getName());
            }
        }
        tx.commit();
        session.close();
    }
    
    public List<Employee> getAllEmployee(){
        Session session = factory.openSession();
        Transaction tx = null;
        
        tx = session.beginTransaction();
        List<Employee> emps = session.createQuery("FROM Employee").list();
        tx.commit();
        session.close();
        return emps;
    }
    
    public void updateEmployee(int employeeId, int salary){
        Session session = factory.openSession();
        Transaction tx = null;
        
        tx = session.beginTransaction();
        Employee emp = session.get(Employee.class, employeeId);
        emp.setSalary(salary);
        session.update(emp);
        tx.commit();
        session.close();        
    }
    
    public void deleteEmployee(int employeeId){
        Session session = factory.openSession();
        Transaction tx = null;
        
        tx = session.beginTransaction();
        Employee employee = session.get(Employee.class, employeeId);
        session.delete(employee);
        tx.commit();
        session.close();
    }
}

 

App.java 應用入口類,演示本例子。

package tony.hibernateList;

import java.util.ArrayList;
import java.util.List;

public class App 
{
    public static void main( String[] args )
    {        
        ManageEmployee me = new ManageEmployee();
        
        ArrayList<Certificate> cert = new ArrayList<>();
        cert.add(new Certificate("MCA"));
        cert.add(new Certificate("MBA"));
        cert.add(new Certificate("PMP"));
        Integer empID1 = me.addEmployee("Manoj", "Kumar", 4000, cert);
        System.out.println(empID1);

        cert = new ArrayList<>();
        cert.add(new Certificate("HHH"));
        cert.add(new Certificate("BBB"));
        cert.add(new Certificate("CCC"));
        Integer empID2 = me.addEmployee("TTT", "FFF", 4000, cert);
        System.out.println(empID2);
        
        me.listEmployee();
        
        List<Employee> employees = me.getAllEmployee();
        Employee last2emp = employees.get(employees.size() - 2);
        me.deleteEmployee(last2emp.getId());
        
        System.out.println("End");
    }
}

 

hibernate.cfg.xml,存儲數據庫信息。打開 show_sql 選項,能夠輸出最終執行的 SQL 語句。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "http://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>

        <!-- Assume test is the database name -->
        <property name="hibernate.connection.url">
            jdbc:mysql://localhost/hibernateTest
        </property>
        <property name="hibernate.connection.username">
            username
        </property>
        <property name="hibernate.connection.password">
            password
        </property>

        <property name="show_sql">true</property>

        <!-- List of XML mapping files -->
        <mapping resource="Employee.hbm.xml" />

    </session-factory>
</hibernate-configuration>

 

參考資料

Hibernate - List Mappings, tutorialspoint

相關文章
相關標籤/搜索