Hibernate 、继承关联映射
一个继承树一张表(subclass)
一个继承树一张表是指将一个类和他下面的所有派生类的所有的属性都放在一张表中,举例有Employee这个实体,在他下面分别派生了两个类skill和sell,通过Hibernate 通过subclass将Employee和他的派生类的所有属性都存放在一张表中,使用type区分类型:
hibernage.cfg.xml
<hibernate-configuration> <session-factory name="sessionFactory"> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=UTF-8</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"></property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">create</property> <mapping resource="cn/hbm/Employee.hbm.xml" /> </session-factory> </hibernate-configuration>
实体:
public class Employee { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Skiller extends Employee { private String skiller; public String getSkiller() { return skiller; } public void setSkiller(String skiller) { this.skiller = skiller; } }
public class Salesman extends Employee { private String salesman; public String getSalesman() { return salesman; } public void setSalesman(String salesman) { this.salesman = salesman; } }
<hibernate-mapping package="cn.model"> <class name="Employee" table="EMPLOYEE" discriminator-value="0"> <id name="id" column="ID"> <generator class="native"></generator> </id> <discriminator column="type" type="int" /> <property name="name" column="NAME" type="java.lang.String" unique="true" /> <subclass name="Skiller" discriminator-value="1"> <property name="skiller" /> </subclass> <subclass name="Salesman" discriminator-value="2"> <property name="salesman" /> </subclass> </class> </hibernate-mapping>
通过 discriminator-value="0"为其指定不同的类型;
public void saveEmployee(){ Session session=null; Transaction tran=null; try{ Employee e1=new Employee(); e1.setName("Tom"); Skiller e2=new Skiller(); e2.setName("杰克"); e2.setSkiller("skiller"); Salesman e3=new Salesman(); e3.setName("维丝"); e3.setSalesman("salesman"); session=HibernateSessionFactory.getSession(); tran=session.beginTransaction(); session.save(e1); session.save(e2); session.save(e3); tran.commit(); }catch(Exception e){ if(session!=null){ session.close(); } } }
在执行commit以后,Hibernate会生成相应的SQL,并且根据不同的类型为他的type填上不同的值:
每个类映射一张表(joined-subclass)
<hibernate-mapping package="cn.model"> <class name="Employee" table="EMPLOYEE"> <id name="id" column="ID"> <generator class="native"></generator> </id> <property name="name" column="NAME" type="java.lang.String" unique="true" /> <joined-subclass name="Skiller" table="SKILLER"> <key column="EMPLOYEE_ID" /> <property name="skiller" /> </joined-subclass> <joined-subclass name="Salesman" table="SALESMAN"> <key column="EMPLOYEE_ID" /> <property name="salesman" /> </joined-subclass> </class> </hibernate-mapping>
两种继承映射方法混合使用
<hibernate-mapping package="cn.model"> <class name="Employee" table="EMPLOYEE" discriminator-value="0"> <id name="id" column="ID"> <generator class="native"></generator> </id> <discriminator column="type" type="int"/> <property name="name" column="NAME" type="java.lang.String" unique="true" /> <subclass name="Skiller" discriminator-value="1"> <property name="skiller" /> </subclass> <subclass name="Salesman" discriminator-value="2"> <join table="SALESMAN"> <key column="EMPLOYEE_ID" /> <property name="salesman" /> </join> </subclass> </class> </hibernate-mapping>
执行以后Hibernate所创建的表:
Hibernate: create table EMPLOYEE ( ID integer not null auto_increment, type integer not null, NAME varchar(255) unique, skiller varchar(255), primary key (ID) ) Hibernate: create table SALESMAN ( EMPLOYEE_ID integer not null, salesman varchar(255), primary key (EMPLOYEE_ID) ) Hibernate: alter table SALESMAN add index FKA21A20CEFABB3642 (EMPLOYEE_ID), add constraint FKA21A20CEFABB3642 foreign key (EMPLOYEE_ID) references EMPLOYEE (ID)
每个类独立映射一张表:
<hibernate-mapping package="cn.model"> <class name="Employee" table="EMPLOYEE"> <id name="id" column="ID"> <generator class="hilo"></generator> </id> <property name="name" column="NAME" type="java.lang.String" unique="true" /> <union-subclass name="Skiller" table="SKILLER"> <property name="skiller" /> </union-subclass> <union-subclass name="Salesman" table="SALESMAN"> <property name="salesman" /> </union-subclass> </class> </hibernate-mapping>
注:在使用这种映射的时候,主键ID不能使用<generator class="native" /> 了因为在生成主键的时候三个表有可能重复,因此必须要使用不会重复的主键生成器,比如UUID或者上文中用的hilo高低位生成ID;
运行程序 可看到,Hibernate生成的三个表都是独立的三个月,之间都没有关系: