当前位置: 移动技术网 > IT编程>开发语言>Java > 详解Java的Hibernat框架中的Map映射与SortedMap映射

详解Java的Hibernat框架中的Map映射与SortedMap映射

2019年07月22日  | 移动技术网IT编程  | 我要评论
map映射 map映射是一个java集合存储在键 - 值对的元素,并且不允许在列表中重复的元素。 map接口提供三种collection视图,允许map内容看作是一组键-

map映射
map映射是一个java集合存储在键 - 值对的元素,并且不允许在列表中重复的元素。 map接口提供三种collection视图,允许map内容看作是一组键-值集合,或者设置键 - 值映射关系。

map被映射到映射表中一个<map>元素和无序的地图可以在java.util.hashmap中被初始化。

定义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,
  primary key (id)
);

此外,假设每个员工都可以有一个或多个与他/她相关的证书。我们将存储证书的相关信息在一个单独的表,该表具有以下结构:

create table certificate (
  id int not null auto_increment,
  certificate_type varchar(40) default null,
  certificate_name varchar(30) default null,
  employee_id int default null,
  primary key (id)
);

有一个对多(one-to-many )的关系在employee和证书对象之间。

定义pojo类:
让我们实现一个pojo类员工将被用于保存与employee表中的对象和有证书的列表变量的集合。

import java.util.*;

public class employee {
  private int id;
  private string firstname; 
  private string lastname;  
  private int salary;
  private map 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 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 map getcertificates() {
   return certificates;
  }
  public void setcertificates( map certificates ) {
   this.certificates = certificates;
  }
}

我们需要相应的证书表定义另一个pojo类,这样的证书对象可以存储和检索到的证书表。

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;
  }
}

定义hibernate映射文件:
让我们开发指示hibernate如何定义的类映射到数据库表的映射文件。<map>元素将被用于定义所使用的映射的规则。

<?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>
   <map name="certificates" cascade="all">
     <key column="employee_id"/>
     <index column="certificate_type" type="string"/>
     <one-to-many class="certificate"/>
   </map>
   <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="certificate" table="certificate">
   <meta attribute="class-description">
     this class contains the certificate records. 
   </meta>
   <id name="id" type="int" column="id">
     <generator class="native"/>
   </id>
   <property name="name" column="certificate_name" type="string"/>
  </class>

</hibernate-mapping>

应该保存的映射文件中的格式<classname>.hbm.xml。我们保存映射文件中的文件employee.hbm.xml。已经熟悉了大部分的映射细节,但让我们再次看映射文件中的所有元素:

映射文档是具有<hibernate-mapping>为对应于每一个类包含2个<class>元素的根元素的xml文档。

<class>元素被用于定义数据库表从一个java类特定的映射。 java类名指定使用class元素的name属性和使用表属性数据库表名指定。

<meta>元素是可选元素,可以用来创建类的描述。

<id>元素映射在类中的唯一id属性到数据库表的主键。 id元素的name属性是指属性的类和column属性是指在数据库表中的列。 type属性保存了hibernate映射类型,这种类型的映射将会从java转换为sql数据类型。

id元素内的<generator>元素被用来自动生成的主键值。将生成元素的class属性设置为原产于让hibernate拿起无论是identity,sequence或者hilo中的算法来创建主键根据底层数据库的支持能力。

<property>元素用于一个java类的属性映射到数据库表中的列。元素的name属性是指属性的类和column属性是指在数据库表中的列。 type属性保存了hibernate映射类型,这种类型的映射将会从java转换为sql数据类型。

<map>元素用于设置证书和employee类之间的关系。我们使用cascade属性的<map>元素来告诉hibernate来保存证书的对象,同时为employee对象。 name属性设置为定义mapvariable在父类中,在我们的案例中是证书。

<index>的元素用于表示键/值对地图的关键部位。该键将使用一个字符串类型的存储在列certificate_type。

<key>元素是包含外键的父对象,即在证书表中的列。表employee。

<one-to-many>元素表示一个employee对象涉及到很多证书的对象,并因此,证书对象必须有与employee父类有关。可以根据需要使用<one-to-one>,<many-to-one>或<many-to-many>这个元素。

创建应用程序类:
最后,创建应用程序类的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 a set of certificates for the first employee */
   hashmap set = new hashmap();
   set.put("computerscience", new certificate("mca"));
   set.put("businessmanagement", new certificate("mba"));
   set.put("projectmanagement", new certificate("pmp"));
   
   /* add employee records in the database */
   integer empid = me.addemployee("manoj", "kumar", 4000, set);

   /* list down all the employees */
   me.listemployees();

   /* update employee's salary records */
   me.updateemployee(empid, 5000);

   /* list down all the employees */
   me.listemployees();

  }

  /* method to add an employee record in the database */
  public integer addemployee(string fname, string lname, 
                   int salary, hashmap 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;
  }

  /* 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 iterator1 = 
              employees.iterator(); iterator1.hasnext();){
      employee employee = (employee) iterator1.next(); 
      system.out.print("first name: " + employee.getfirstname()); 
      system.out.print(" last name: " + employee.getlastname()); 
      system.out.println(" salary: " + employee.getsalary());
      map ec = employee.getcertificates();
      system.out.println("certificate: " + 
       (((certificate)ec.get("computerscience")).getname()));
      system.out.println("certificate: " + 
       (((certificate)ec.get("businessmanagement")).getname()));
      system.out.println("certificate: " + 
       (((certificate)ec.get("projectmanagement")).getname()));
     }
     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(); 
   }
  }
  /* method to delete an employee from the records */
  public void deleteemployee(integer employeeid){
   session session = factory.opensession();
   transaction tx = null;
   try{
     tx = session.begintransaction();
     employee employee = 
          (employee)session.get(employee.class, employeeid); 
     session.delete(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源文件,如上图所示,并编译它。
  • 创建certificate.java源文件,如上图所示,并编译它。
  • 创建manageemployee.java源文件,如上图所示,并编译它。
  • 执行manageemployee二进制文件来运行程序。

会在屏幕上获得以下结果,并同时创建记录在员工和证书表。

$java manageemployee

.......various log messages will display here........

first name: manoj last name: kumar salary: 4000
certificate: mca
certificate: mba
certificate: pmp
first name: manoj last name: kumar salary: 5000
certificate: mca
certificate: mba
certificate: pmp

如果检查员工和证书表,就应该记录下了:

mysql> select * from employee;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 60 | manoj   | kumar   |  5000 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)

mysql>select * from certificate;
+----+--------------------+------------------+-------------+
| id | certificate_type  | certificate_name | employee_id |
+----+--------------------+------------------+-------------+
| 16 | projectmanagement | pmp       |     60 |
| 17 | businessmanagement | mba       |     60 |
| 18 | computerscience  | mca       |     60 |
+----+--------------------+------------------+-------------+
3 rows in set (0.00 sec)


sortedmap映射
sortedmap是存储在键 - 值对的元素,并提供键的总体排序类似java的集合作为映射。重复的元素未在映射不允许的。该映射是根据其键的自然顺序进行排序,或者通过提供通常在有序映射的创建时间比较。

sortedmap被映射在该映射表中的<map>元素和有序映射可以在java.util.treemap中被初始化。
我们依然使用上面定义的rdbms表和pojo类来讲下面的例子:
定义hibernate映射文件:
让我们开发指示hibernate如何定义的类映射到数据库表的映射文件。<map>元素将被用于定义所使用的映射的规则。

<?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>
   <map name="certificates" cascade="all" sort="myclass">
     <key column="employee_id"/>
     <index column="certificate_type" type="string"/>
     <one-to-many class="certificate"/>
   </map>
   <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="certificate" table="certificate">
   <meta attribute="class-description">
     this class contains the certificate records. 
   </meta>
   <id name="id" type="int" column="id">
     <generator class="native"/>
   </id>
   <property name="name" column="certificate_name" type="string"/>
  </class>

</hibernate-mapping>

应该保存的映射文件中的格式<classname>.hbm.xml。我们保存映射文件employee.hbm.xml。前面已经熟悉了大部分的映射细节,但让我们再次看看映射文件中的所有元素:

映射文档是具有<hibernate-mapping>对应于每一个类包含2个<class>元素的根元素的xml文档。

<class>元素被用于定义数据库表从一个java类特定的映射。 java类名指定使用class元素的name属性和使用表属性数据库表名指定。

<meta>元素是可选元素,可以用来创建类的描述。

<id>元素映射在类中的唯一id属性到数据库表的主键。 id元素的name属性是指属性的类和column属性是指在数据库表中的列。 type属性保存了hibernate映射类型,这种类型的映射将会从java转换为sql数据类型。

id元素内的<generator>元素被用来自动生成的主键值。将生成元素的class属性设置让hibernate对应于identity,sequence或者hilo中的算法来创建主键根据底层数据库的支持能力。

<property>元素用于一个java类的属性映射到数据库表中的列。元素的name属性是指属性的类和column属性是指在数据库表中的列。 type属性保存了hibernate映射类型,这种类型的映射将会从java转换为sql数据类型。

<map>元素用于设置证书和employee类之间的关系。我们使用cascade属性的<map>元素来告诉hibernate来保存证书的对象,同时为employee对象。 name属性被设置为在父类中的定义的sortedmap变量,在我们的情况下,它是证书。排序属性可以设置为自然有自然排序,也可以设置为自定义类实现为java.util.comparator。我们已经使用了一个类myclass,它实现为java.util.comparator扭转证书类实现的排序顺序。

<index>元素用于表示键/值对映射的键部分。该键将使用一个字符串类型的存储在列certificate_type。

<key>元素是包含外键的父对象,即在证书表中的列。表employee。

<one-to-many>元素表示一个employee对象涉及到很多证书的对象,并因此,证书对象必须有与employee父有关联。可以根据需要使用<one-to-one>,<many-to-one>或<many-to-many>这个元素。

如果使用sort="natural",然后我们并不需要创建一个单独的类,因为证书类已经实现了comparable接口和hibernate会使用compareto在证书类定义为比较的sortedmap()方法。但是,我们使用的是在我们的映射文件自定义的比较器类myclass,所以我们必须创建这个类的基础上我们的排序算法。让我们做降在映射上可用的按键排序。

import java.util.comparator;

public class myclass implements comparator <string>{
  public int compare(string o1, string o2) {
   final int before = -1;
   final int after = 1;

   /* to reverse the sorting order, multiple by -1 */
   if (o2 == null) {
     return before * -1;
   }

   comparable thiscertificate = o1;
   comparable thatcertificate = o2;

   if(thiscertificate == null) {
     return after * 1;
   } else if(thatcertificate == null) {
     return before * -1;
   } else {
     return thiscertificate.compareto(thatcertificate) * -1;
   }
  }
}

最后,我们将创建应用程序类的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 a set of certificates for the first employee */
   treemap set1 = new treemap();
   set1.put("computerscience", new certificate("mca"));
   set1.put("businessmanagement", new certificate("mba"));
   set1.put("projectmanagement", new certificate("pmp"));
 
   /* add employee records in the database */
   integer empid1 = me.addemployee("manoj", "kumar", 4000, set1);

   /* another set of certificates for the second employee */
   treemap set2 = new treemap();
   set2.put("computerscience", new certificate("mca"));
   set2.put("businessmanagement", new certificate("mba"));

   /* add another employee record in the database */
   integer empid2 = me.addemployee("dilip", "kumar", 3000, set2);

   /* list down all the employees */
   me.listemployees();

   /* update employee's salary records */
   me.updateemployee(empid1, 5000);

   /* delete an employee from the database */
   me.deleteemployee(empid2);

   /* list down all the employees */
   me.listemployees();

  }

  /* method to add an employee record in the database */
  public integer addemployee(string fname, string lname, 
                   int salary, treemap 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;
  }

  /* 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 iterator1 = 
              employees.iterator(); iterator1.hasnext();){
      employee employee = (employee) iterator1.next(); 
      system.out.print("first name: " + employee.getfirstname()); 
      system.out.print(" last name: " + employee.getlastname()); 
      system.out.println(" salary: " + employee.getsalary());
      sortedmap<string, certificate> map = 
                        employee.getcertificates();
      for(map.entry<string,certificate> entry : map.entryset()){
        system.out.print("\tcertificate type: " + entry.getkey());
        system.out.println(", name: " + 
                    (entry.getvalue()).getname());
      }
     }
     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(); 
   }
  }
  /* method to delete an employee from the records */
  public void deleteemployee(integer employeeid){
   session session = factory.opensession();
   transaction tx = null;
   try{
     tx = session.begintransaction();
     employee employee = 
          (employee)session.get(employee.class, employeeid); 
     session.delete(employee); 
     tx.commit();
   }catch (hibernateexception e) {
     if (tx!=null) tx.rollback();
     e.printstacktrace(); 
   }finally {
     session.close(); 
   }
  }
}

编译和执行: 
可以看到证书已排序顺序相反。可以通过改变映射文件试试,只需设置sort="natural"和执行程序,并比较结果。

$java manageemployee
.......various log messages will display here........

first name: manoj last name: kumar salary: 4000
 certificate type: projectmanagement, name: pmp
 certificate type: computerscience, name: mca
 certificate type: businessmanagement, name: mba
first name: dilip last name: kumar salary: 3000
 certificate type: computerscience, name: mca
 certificate type: businessmanagement, name: mba
first name: manoj last name: kumar salary: 5000
 certificate type: projectmanagement, name: pmp
 certificate type: computerscience, name: mca
 certificate type: businessmanagement, name: mba

如果检查员工和证书表,就应该记录下了:

mysql> select * from employee;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 74 | manoj   | kumar   |  5000 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)

mysql> select * from certificate;
+----+--------------------+------------------+-------------+
| id | certificate_type  | certificate_name | employee_id |
+----+--------------------+------------------+-------------+
| 52 | businessmanagement | mba       |     74 |
| 53 | computerscience  | mca       |     74 |
| 54 | projectmanagement | pmp       |     74 |
+----+--------------------+------------------+-------------+
3 rows in set (0.00 sec)

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网