服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

精通hibernate之映射继承关系三


  <hibernate-mapping >
  <class name="mypack.salariedemployee" table="salaried_employees">
  <id name="id" type="long" column="id">
  <generator class="increment"/>
  </id>
  
  <property name="name" type="string" column="name" />
  <property name="salary" column="salary" type="double" />
  
  <many-to-one
  name="company"
  column="company_id"
  class="mypack.company"
  />
  </class>
  </hibernate-mapping>
  
  由于employee类没有相应的映射文件,因此在初始化hibernate时,只需向configuration对象中加入company类、hourlyemployee类和salariedemployee类:
  
  configuration config = new configuration();
  config.addclass(company.class)
  .addclass(hourlyemployee.class)
  .addclass(salariedemployee.class);
  
  14.1.2 操纵持久化对象
  
  这种映射方式不支持多态查询,在本书第11章的11.1.6节(多态查询)介绍了多态查询的概念。对于以下查询语句:
  
  list employees=session.find("from employee");
  
  如果employee类是抽象类,那么hibernate会抛出异常。如果employee类是具体类,那么hibernate仅仅查询employees表,检索出employee类本身的实例,但不会检索出它的两个子类的实例。本节的范例程序位于配套光盘的sourcecode/chapter14/14.1目录下,运行该程序前,需要在sampledb数据库中手工创建companies表、he表和se表,然后加入测试数据,相关的sql脚本文件为/14.1/schema/sampledb.sql。
  
  在chapter14目录下有四个ant的工程文件,分别为build1.xml、build2.xml、build3.xml和build4.xml,它们的区别在于文件开头设置的路径不一样,例如在build1.xml文件中设置了以下路径:
  
  <property name="source.root" value="14.1/src"/>
  <property name="class.root" value="14.1/classes"/>
  <property name="lib.dir" value="lib"/>
  <property name="schema.dir" value="14.1/schema"/>
  
  在dos命令行下进入chapter14根目录,然后输入命令:
  
  ant -file build1.xml run
  
  就会运行businessservice类。ant命令的-file选项用于显式指定工程文件。businessservice类用于演示操纵employee类的对象的方法,例程14-4是它的源程序。
  
  例程14-4 businessservice.java
  
  public class businessservice{
  public static sessionfactory sessionfactory;
  static{
  try{
  configuration config = new configuration();
  config.addclass(company.class)
  .addclass(hourlyemployee.class)
  .addclass(salariedemployee.class);
  sessionfactory = config.buildsessionfactory();
  }catch(exception e){e.printstacktrace();}
  }
  
  public void saveemployee(employee employee) throws exception{……}
  public list findallemployees() throws exception{……}
  public company loadcompany(long id) throws exception{……}
  
  public void test() throws exception{
  list employees=findallemployees();
  printallemployees(employees.iterator());
  
  company company=loadcompany(1);
  printallemployees(company.getemployees().iterator());
  
  employee employee=new hourlyemployee("mary",300,company);
  saveemployee(employee);
  
  }
  
  private void printallemployees(iterator it){
  while(it.hasnext()){
  employee e=(employee)it.next();
  if(e instanceof hourlyemployee){
  system.out.println(((hourlyemployee)e).getrate());
  }else
  system.out.println(((salariedemployee)e).getsalary());
  }
  }
  public static void main(string args[]) throws exception {
  new businessservice().test();
  sessionfactory.close();
  }
  }
  businessservice的main()方法调用test()方法,test()方法依次调用以下方法。
  findallemployees():检索数据库中所有的employee对象。
  loadcompany():加载一个company对象。
  saveemployee():保存一个employee对象。
  
  (1)运行findallemployees()方法,它的代码如下:
  
  list results=new arraylist();
  tx = session.begintransaction();
  list hourlyemployees=session.find("from hourlyemployee");
  results.addall(hourlyemployees);
  
  list salariedemployees=session.find("from salariedemployee");
  results.addall(salariedemployees);
  
  tx.commit();
  return results;
  
  为了检索所有的employee对象,必须分别检索所有的hourlyemployee实例和salariedemployee实例,然后把它们合并到同一个集合中。在运行session的第一个find()方法时,hibernate执行以下select语句:
  
  select * from hourly_employees;
  select * from companies where id=1;
  
  从hourlyemployee类到company类不是多态关联,在加载hourlyemployee对象时,会同时加载与它关联的company对象。
  
  在运行session的第二个find()方法时,hibernate执行以下select语句:
  
  select * from salaried_employees;
  
  从salariedemployee类到company类不是多态关联,在加载salariedemployee对象时,会同时加载与它关联的company对象。在本书提供的测试数据中,所有hourlyemployee实例和salariedemployee实例都与oid为1的company对象关联,由于该company对象已经被加载到内存中,所以hibernate不再需要执行检索该对象的select语句。
  
  (2)运行loadcompany()方法,它的代码如下:
  
  tx = session.begintransaction();
  company company=(company)session.load(company.class,new long(id));
  
  list hourlyemployees=session.find("from hourlyemployee h where h.company.id="+id);
  company.getemployees().addall(hourlyemployees);
  
  list salariedemployees=session.find("from salariedemployee s where s.company.id="+id);
  company.getemployees().addall(salariedemployees);
  
  tx.commit();
  return company;
  
  由于这种映射方式不支持多态关联,因此由session的load()方法加载的company对象的employees集合中不包含任何employee对象。businessservice类必须负责从数据库中检索出所有与company对象关联的hourlyemployee对象以及salariedemployee对象,然后把它们加入到employees集合中。
  
  (3)运行saveemployee(employee employee)方法,它的代码如下:
  
  tx = session.begintransaction();
  session.save(employee);
  tx.commit();
  
  在test()方法中,创建了一个hourlyemployee实例,然后调用saveemployee()方法保存这个实例:
  
  employee employee=new hourlyemployee("mary",300,company);
  saveemployee(employee);
  
  session的save()方法能判断employee变量实际引用的实例的类型,如果employee变量引用hourlyemployee实例,就向he表插入一条记录,执行如下insert语句:
  
  insert into hourly_employees(id,name,rate,customer_id)
  values(3, 'mary',300,1);
  
  如果employee变量引用salariedemployee实例,就向se表插入一条记录。

扫描关注微信公众号