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>
參考資料