实现方式一般有三种:
1. 继承关系树每个具体类对应一张表(不介绍)
2. 继承关系树的根类对应一张表
3. 继承关系树的每个类对应一张表
先介绍关系:
DayEmployee和MonthEmploy是Employee的子类,并且Company和Employee是一对多关系:
具体代码如下:
Company.java
import java.util.HashSet;
import java.util.Set;
public class Company {
private Integer id;
private String name;
private Set<Employee> employees = new HashSet<Employee>();
public Company() {
super();
}
public Company(String name) {
super();
this.name = 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 Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}
Employee.java
public class Employee {
private Integer id;
private String name;
private Integer age;
private Company company;
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
DayEmployee.java
public class DayEmployee extends Employee{
private Double dayMoney;
public Double getDayMoney() {
return dayMoney;
}
public void setDayMoney(Double dayMoney) {
this.dayMoney = dayMoney;
}
}
MonthEmploy.java
public class MonthEmploy extends Employee{
private Double monthMoney;
public Double getMonthMoney() {
return monthMoney;
}
public void setMonthMoney(Double monthMoney) {
this.monthMoney = monthMoney;
}
}
Company.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.dongecs.test1.pojo">
<class name="Company" table="COMPANY">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<set name="employees" table="EMPLOYEE" inverse="true" lazy="true">
<key>
<column name="COMPANY" />
</key>
<one-to-many class="Employee" />
</set>
</class>
</hibernate-mapping>
继承关系树的根类对应一张表对应的Employee.hbm.xml的写法
Employee.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.dongecs.test1.pojo">
<!-- 利用discriminator-value默认 empType 的值为emp -->
<class name="Employee" table="EMPLOYEE" discriminator-value="emp">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<!--用于识别此类的类别 -->
<discriminator column="empType" type="string"/>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="java.lang.Integer">
<column name="AGE" />
</property>
<many-to-one name="company" class="Company" fetch="join">
<column name="COMPANY" />
</many-to-one>
<!-- 若为DayEmployee,那么将empType的值设为DE -->
<subclass name="DayEmployee" discriminator-value="DE">
<property name="dayMoney" type="double"></property>
</subclass>
<!-- 若为MonthEmploy,那么将empType的值设为ME -->
<subclass name="MonthEmploy" discriminator-value="ME">
<property name="monthMoney" type="double"></property>
</subclass>
</class>
</hibernate-mapping>
利用上述代码作如下测试:
public class EmployeeTest {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
@Before
public void init() {
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void after() {
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testEmployee() {
Company company = new Company("com1");
DayEmployee d1 = new DayEmployee();
d1.setAge(22);
d1.setDayMoney(50.0);
d1.setName("d1");
MonthEmploy d2 = new MonthEmploy();
d2.setAge(30);
d2.setMonthMoney(79.0);
d2.setName("d2");
Employee employee = new Employee();
employee.setAge(90);
employee.setName("employee");
d1.setCompany(company);
d2.setCompany(company);
employee.setCompany(company);
//inverse = true 时可以关联, 当相对多出3条update,因此建议使用多的一端关联
// company.getEmployees().add(employee);
// company.getEmployees().add(d1);
// company.getEmployees().add(d2);
//把一的一段放到最前保存,可以减小3条更新操作
session.save(company);
session.save(employee);
session.save(d2);
session.save(d1);
}
}
会得出如下结果:
继承关系树的每个类对应一张表Employee.hbm.xml的写法
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.dongecs.test1.pojo">
<class name="Employee" table="EMPLOYEE">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="java.lang.Integer">
<column name="AGE" />
</property>
<many-to-one name="company" class="Company" fetch="join">
<column name="COMPANY" />
</many-to-one>
<!-- 利用joined-subclass表签外键关联MonthEmploy -->
<joined-subclass name="MonthEmploy" table="MONEMPLOY">
<key column="EMPLOYEE_ID"></key>
<property name="monthMoney" type="double"></property>
</joined-subclass>
<joined-subclass name="DayEmployee" table="DAYEMPLOY">
<key column="EMPLOYEE_ID"></key>
<property name="dayMoney" type="double"></property>
</joined-subclass>
</class>
</hibernate-mapping>
测试代码:
public class EmployeeTest {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
@Before
public void init() {
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void after() {
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testEmployee() {
Company company = new Company("com1");
DayEmployee d1 = new DayEmployee();
d1.setAge(22);
d1.setDayMoney(50.0);
d1.setName("d1");
MonthEmploy d2 = new MonthEmploy();
d2.setAge(30);
d2.setMonthMoney(79.0);
d2.setName("d2");
Employee employee = new Employee();
employee.setAge(90);
employee.setName("employee");
d1.setCompany(company);
d2.setCompany(company);
employee.setCompany(company);
//inverse = true 时可以关联, 当相对多出3条update,因此建议使用多的一端关联
// company.getEmployees().add(employee);
// company.getEmployees().add(d1);
// company.getEmployees().add(d2);
//把一的一段放到最前保存,可以减小3条更新操作
session.save(company);
session.save(employee);
session.save(d2);
session.save(d1);
}
@Test
public void findFromEmployeeTable(){
String hql = "from Employee";
//通过左外链接找
List<Employee> list = session.createQuery(hql).list();
for (Employee emp : list){
if (emp instanceof DayEmployee){
System.out.println("day");
} else if (emp instanceof MonthEmploy){
System.out.println("mon");
} else {
System.out.println("emp");
}
}
}
@Test
public void findFromDayEmployeeTable(){
String hql = "from DayEmployee";
//通过内连接找
List<Employee> list = session.createQuery(hql).list();
System.out.println(list.size());
}
}
得出如下结果:
结论:
1.使用根类对应一张表
好处:只需创建一张表,不用外键关联
缺点:如果子类属性多,会导致另一子类有过多的空值,而且不能设置一些字段的not null约束,因此不能保证数据库的完整性
2.每个类对应一张表(外键关联)
好处:如果某个类的属性发生变化,只需修改和这个类对应的表
缺点:利用外键关联查询
ref:
孙卫琴.精通Hibernate:Java对象持久化技术详解
时间: 2024-10-10 18:14:55