首页 > 代码库 > [Hibernate] List 映射例子

[Hibernate] List 映射例子

List 是 java 集合的一个工具,存储线性的数据,允许重复数据。开发者可以准确控制在 list 那个位置插入数据。本例子演示 Java 的 List 集合和 MySQL 数据库的映射应用。

使用场景:一个员工有一个或多个证书,对员工以及其拥有的证书进行增删该查操作。这个一个 1 : n的场景。

代码的目录结构如下:

技术分享

hibernate.cfg.xml 存储数据库信息,如数据库类型,账号密码,数据库名称。

Empoyee.hbm.xml,声明 Employee 对象及其属性和数据库表结构的对应关系。其中,Employee 的属性包括一个 Certificate 的 List 集合。后面详细介绍此文件。

Employee.java,Employee 实体类。

Certificate.java, Certificate 实体类。

ManageEmployee.java,管理 Employee,并对外提供操作 Employee 对象数据的接口。

App.java,演示本例子。

 

代码详情

EMPLOYEE, CERTIFICATE 在 MySQL 中的建表语句。

虽然 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

 

[Hibernate] List 映射例子