分类: J2EE2011-11-30 01:53 948人阅读 评论(0) 收藏 举报html
hibernateclassnulltablestringjoinjava
Java类中有继承关系,相应的在hibernate中,也有继承关系,子类反应到数据库中,就有多种实现形式了,子类和父类能够映射到同一张表中,子类也能够单独映射成一张表,可是用不一样的标签实现,子类表和父类表的关系也不一样。在映射文件中,有三个标签能够实现继承关系,分别是:subclass、joined-subclass、union-subclass,先陈述一下这三个标签的区别:sql
subclass标签就是为子类嵌入父类的表中而设计的,并且要指定鉴别器,即用subclass必定要有判断类型的一个列,鉴别器指定记录属于哪一个类型。可是subclass也提供了为子类设置单独的表的功能,即join标签。可是无论是内嵌表仍是外部表,都得指定鉴别器。数据库
joined-subclass标签,提供的功能是只能为子类设定外部表,并且没有鉴别器,即子类一张表,父类一张表,子类以父类的主键为外键。父类对应的表中,没有判断类型的列。spa
注意:这两个标签不能混用,如果只想要内嵌表,或者是既想要有内嵌表,又想要外部表,又或者是只想要外部表,那么只能使用subclass标签,须要注意的是,不论哪一种方式,都要指定鉴别器,即父类对应的表中,必定有一个判断类型的列;而如果只想要外部表,又不想在父类对应的表中,要那个判断类型的列,那么只能使用join-subclass.net
union-subclass是将父类中的属性,添加到子类对应的表中去了。包括父类中的外键。union-class和前两个的区别就在于外键的不一样,前两个标签,若是子类有单独对应的表的话,这个表的外键是其父类中的主键,而使用union-class,子类对应的表中的外键则和父类的外键是同样的,由于子类把父类继承的属性,也加到了本身的表当中。这样子类和父类的地位就至关了。不过这不是一种好的理解方式。若是是这样的话,那么就能够把父类设为抽象的类,而且在映射文件中,把父类设置为abstract="true",那么就不会再数据库中生成父类对应的表了,父类就只起到一个抽象的做用了。hibernate
下面列举员工和部门的例子说明,假设员工类还有两个子类:一个是技术人员,一个是销售人员:设计
[java] view plaincopyhtm
public class Employee { blog
private int id;
private String name;
private Department depart;
……//set/get方法
}
[java] view plaincopy
public class Skiller extends Employee {
private String skill;
……//set/get方法
}
[java] view plaincopy
public class Saler extends Employee {
private String sale;
private int age;
……//set/get方法
}
[java] view plaincopy
public class Department {
private int id;
private String name;
private Set<Employee> emps;
……//set/get方法
}
部门类的映射文件:
[html] view plaincopy
<class name="Department">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="emps" inverse="true">
<key column="depart_id"/>
<one-to-many class="Employee"/>
</set>
</class>
(1)下面关键是员工类的映射文件,咱们先来看使用subclass标签的状况:
[html] view plaincopy
<class name="Employee" discriminator-value="0">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="type" type="int"/><!-- 指定了鉴别器 -->
<property name="name"/>
<many-to-one name="depart" column="depart_id"/>
<subclass name="Skiller" discriminator-value="1">
<property name="skill"/>
</subclass>
<subclass name="Saler" discriminator-value="2">
<property name="sale"/>
</subclass>
</class>
这种状况就是所谓的将整个继承树映射到同一个表当中,即子类的信息,所有映射到了父类对应的表中。注意,必定要指定鉴别器,它的做用是在父类的映射表中,添加了一个type的列,用来鉴别员工是属于哪一个子类,而且在每一个类的标签中要指定鉴别器值,如上例中用0表示是普通的员工,用1表示技术人员,用2表示销售人员。咱们能够看看建立表的ddl语句:
[sql] view plaincopy
CREATE TABLE `employee` (
`id` int(11) NOT NULL,
`type` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`depart_id` int(11) DEFAULT NULL,
`skill` varchar(255) DEFAULT NULL,
`sale` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK4AFD4ACE972E0614` (`depart_id`),
CONSTRAINT `FK4AFD4ACE972E0614` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
用这种方式有缺点有优势,缺点是在表中,会有不少的空值,假如又有了新的子类,那么就要修改表的结构,而且相应的空值会更多;优势是全部信息整合到一张表中,查询的效率高。
下面再来看subclass标签的第二种用法:
[html] view plaincopy
<class name="Employee" discriminator-value="0"><!-- discriminator-value="0" -->
<id name="id">
<generator class="native"/>
</id>
<discriminator column="type" type="int"/><!-- 指定了鉴别器 -->
<property name="name"/>
<many-to-one name="depart" column="depart_id"/>
<subclass name="Skiller" discriminator-value="1">
<property name="skill"/>
</subclass>
<subclass name="Saler" discriminator-value="2">
<join table="saler">
<key column="emp_id"/>
<property name="sale"/>
</join>
</subclass>
</class>
改变的地方,主要是Saler类的标签,在subclass标签中用join标签,这样就为Saler子类单独映射了一个saler表,其主键为父类对应的表的主键。而Skiller类仍是和父类映射到了一张表中。来看看Saler建立表的ddl语句:
[sql] view plaincopy
CREATE TABLE `saler` (
`emp_id` int(11) NOT NULL,
`sale` varchar(255) DEFAULT NULL,
PRIMARY KEY (`emp_id`),
KEY `FK682490B3F739201` (`emp_id`),
CONSTRAINT `FK682490B3F739201` FOREIGN KEY (`emp_id`) REFERENCES `employee` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
须要注意的一个地方是这个表的外键,外键和主键是同样的,都是父类表的主键。
(2)joined-subclass的使用
[html] view plaincopy
<class name="Employee"><!-- discriminator-value="0" -->
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="depart" column="depart_id"/>
<joined-subclass name="Skiller" table="skiller">
<key column="emp_id"/>
<property name="skill"/>
</joined-subclass>
<joined-subclass name="Saler" table="saler">
<key column="emp_id"/>
<property name="sale"/>
</joined-subclass>
</class>
用joined-subclass只能建立为子类单首创建表,子类对应的表的主键和外键都是其父类的主键。注意,joined-subclass不能和subclass混合使用。
(3)union-subclass的使用
[html] view plaincopy
<class name="Employee">
<id name="id">
<generator class="hilo"/>
</id>
<property name="name"/>
<many-to-one name="depart" column="depart_id"/>
<union-subclass name="Skiller" table="skiller">
<property name="skill"/>
</union-subclass>
<union-subclass name="Saler" table="saler">
<property name="age"/>
<property name="sale"/>
</union-subclass>
</class>
注意,这里主键的生成方式就不能是自增的了,这里用的hilo方式,能够为子类的表分配和父类的表不一样的主键。这样每一个子类生成了一个表,而且结合了父类中的属性。生成的表的ddl语句为:
[sql] view plaincopy
CREATE TABLE `skiller` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`depart_id` int(11) DEFAULT NULL,
`skill` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK4AFD4ACE972E06147ffd86be` (`depart_id`),
CONSTRAINT `FK4AFD4ACE972E06147ffd86be` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
注意,这里的外键是部门类对应的表的主键,这是和上面两个标签的区别之处。如果将父类设置为抽象类,而且在class标签中设置abstract="true",那么父类就不会生成对应的表了。