11.映射继承关系

来源:互联网 发布:口袋助理源码 编辑:程序博客网 时间:2024/06/09 19:49

1.采用 subclass 元素的继承映射

*   每个具体类一张表(table per concrete class) 将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态。

*   父类和子类使用同一张表(有一个区分类型的字段)

*   采用 subclass 的继承映射可以实现对于继承关系中父类和子类使用同一张表

*   因为父类和子类的实例全部保存在同一个表中,因此需要在该表内增加一列,使用该列来区分每行记录到底是哪个类的实例----这个列被称为辨别者列(discriminator).

/** * 钟点工 */public class HourEmployee  extends Employee{
/** * 正式员工 */public class SalaryEmployee extends Employee {
hibernate配置文件

<hibernate-mapping>  <class name="cn.itcast.extends01.Employee" table="employee" discriminator-value="ee">      <id name="id" type="integer">        <column name="id"/>        <generator class="increment"/>      </id>      <!--辨别者列,column="etype"用于区分员工的种类,该配置必须放置在id的后面-->      <discriminator column="etype" type="string"/>      <property name="name" type="string">          <column name="name"/>      </property>      <!--配置子类           discriminator-value: 子类对应的辨别者列的值        -->      <subclass name="cn.itcast.extends01.HourEmployee" discriminator-value="he">        <property name="rate" column="rate" type="double"/>       </subclass>      <subclass name="cn.itcast.extends01.SalaryEmployee" discriminator-value="se">        <property name="salary" column="salary" type="double"/>      </subclass>  </class>  </hibernate-mapping>
*   辨别者列,用于区分员工的种类,该配置必须放置在id的后面

*   普通员工的辨别者列值为ee,小时工辨别者列的值为he,正式员工的辨别者列的值为se
*   在这种映射策略下,使用 subclass 来映射子类,使用 class 或 subclass 的 discriminator-value 属性指定辨别者列的值

*   所有子类定义的字段都不能有非空约束。如果为那些字段添加非空约束,那么父类的实例在那些列其实并没有值,这将引起数据库完整性冲突,导致父类的实例无法保     存到数据库中

SalaryEmployee se=new SalaryEmployee();se.setName("赵敏");se.setSalary(3000d);
*   double类型的值要加个d,默认数字都是int类型

1.1查询钟点工信息

@Testpublic  void findHourEmployee(){   Session session=sf.openSession();   Transaction tx=session.beginTransaction();   //可以使用子类   Query query=session.createQuery("from HourEmployee");   query.list();   tx.commit();   session.close();}
查询语句  Hibernate: select houremploy0_.id as id0_, houremploy0_.name as name0_, houremploy0_.rate as rate0_ from employee houremploy0_ where houremploy0_.etype='he'

*   如果查询所有员工,hql语句为 from Employee  多态查询
2.采用 joined-subclass 元素的继承映射

*   采用 joined-subclass 元素的继承映射可以实现每个子类一张表

*   采用这种映射策略时,父类实例保存在父类表中,子类实例由父类表和子类表共同存储。因为子类实例也是一个特殊的父类实例,因此必然也包含了父类实例的属性。     于是将子类和父类共有的属性保存在父类表中,子类增加的属性,则保存在子类表中

 <hibernate-mapping> <class name="cn.itcast.extends02.Employee" table="e_emp" >      <id name="id" type="integer">        <column name="id"/>        <generator class="increment"/>      </id>      <property name="name" type="string">          <column name="name"/>      </property>    <!--       使用joined-subclass映射子类         name="cn.itcast.extends02.HourEmployee":子类的类的完整路径         table="h_emp":子类对应的表    -->     <joined-subclass name="cn.itcast.extends02.HourEmployee" table="h_emp">        <!--表示h_emp 表中的主键,同时又是外键-->        <key column="hid"/>        <property name="rate" column="rate" type="double"/>    </joined-subclass>        <joined-subclass name="cn.itcast.extends02.SalaryEmployee" table="s_emp">        <key column="sid"/>        <property name="salary" column="salary" type="double"/>    </joined-subclass>  </class>  </hibernate-mapping>
*   子类增加的属性可以添加非空约束。因为子类的属性和父类的属性没有保存在同一个表中
*   在这种映射策略下,无须使用鉴别者列,但需要为每个子类使用 key 元素映射共有主键,该主键必须与父类标识属性的列名相同。
2.1.删除员工信息

@Testpublic  void removeEmployee(){   Session session=sf.openSession();   Transaction tx=session.beginTransaction();   Employee e2=(Employee)session.get(Employee.class, 2);   session.delete(e2);   tx.commit();   session.close();}
*   删除员工信息,不用使用级联

2.2.查询唯一的员工,不是钟点工也不是正式员工

@Testpublic  void findUniqueEmployee(){   Session session=sf.openSession();   Transaction tx=session.beginTransaction();   //sql SELECT * FROM e_emp e WHERE e.id NOT IN(SELECT hid FROM h_emp) AND e.id NOT IN(SELECT sid FROM s_emp)   Query query=session.createQuery("from Employee e where e.id not in(select h.id from HourEmployee h) and e.id not in(select s.id from SalaryEmployee s)");   query.list();   tx.commit();   session.close();}

3.项目改造

 <!-- 加载映射文件-->      <mapping resource="cn/itcast/add/Customer.hbm.xml"/>      <mapping resource="cn/itcast/add/Order.hbm.xml"/>
*   在Hibernate配置文件加载映射文件

Customer.hbm.xml

 <class name="cn.itcast.add.Customer" table="customers" entity-name="customersk">      <id name="id" type="integer">        <column name="id"/>        <generator class="increment"/>      </id>      <property name="name" type="string">          <column name="name"/>      </property>      <set name="orderes" table="orders" inverse="true">         <key>           <column name="customer_id"/>         </key>          <one-to-many entity-name="ordersk"/>      </set>         </class>
Order.hbm.xml
 <class name="cn.itcast.add.Order" table="orders" entity-name="ordersk">      <id name="id" type="integer">        <column name="id"/>        <generator class="increment"/>      </id>      <property name="orderNumber" type="string">          <column name="orderNumber"/>      </property>      <property name="price" type="double">          <column name="price"/>      </property>           <many-to-one  name="customer" entity-name="customersk">           <column name="customer_id"/>      </many-to-one>         </class>
*   entity-name:表示实体的名称  相当于起了一个别名

3.1.项目改造(保存save)

session.save("customersk",customer);
3.2.项目改在(修改

@Testpublic void updateCustomer(){CustomerDao customerDao=new CustomerDao();Customer customer=new Customer();customer.setId(1);customer.setName("西门公子");customerDao.updateCustomer(customer);}
*   这种方式的修改的是新建一个对象,再使用update方法,临时对象没有在一级缓存里面,每次都会有update语句,不管属性有没有变

3.3.项目改造(查询list)

public List<Customer> findCustomers() {Session session=null;Transaction tx=null;List<Customer> list=null;try {session=HibernateUtil.getSession();if(session!=null){   tx=HibernateUtil.beginTransaction(session);   Query query=session.createQuery("from customersk");   list=query.list();      HibernateUtil.commitTransaction(tx);}} catch (HibernateException e) {e.printStackTrace();    //事务回滚HibernateUtil.rollbackTransaction(tx);}finally{HibernateUtil.closeSession(session);}return list;}
*   hql语句为from  customersk      customersk别名  

0 0
原创粉丝点击