继承映射(一)整个类继承树只一张表SINGLE_TABLE

根类一张表,将所有子类的属性都合并到根类中,此外还需要一个字段用于区分子类的类型。

company:

package com.persia.singletable;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;

@Entity
@Table(name="company")
public class Company implements Serializable {
   
	private Integer id;
	private String name;
	private Set<Employee> employees=new HashSet<Employee>();
	
	@Id
	@GeneratedValue
	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;
	}
	
	@OneToMany(mappedBy="company",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	@OrderBy(value="id asc")
	public Set<Employee> getEmployees() {
		return employees;
	}
	public void setEmployees(Set<Employee> employees) {
		this.employees = employees;
	}
	
	public void addEmployee(Employee em){
		if(!this.employees.contains(em)){
			this.employees.add(em);
			em.setCompany(this);
		}
	}
	
	public void removeEmployee(Employee em){
		em.setCompany(null);
		this.employees.remove(em);
	}
}

 

Employee:

package com.persia.singletable;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.JoinColumn;

@Entity
@Table(name="employee")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="Discriminator",discriminatorType=DiscriminatorType.STRING,length=30)
public class Employee implements Serializable {

	private Integer id;
	private String name;
	private Company company;
	
	@Id
	@GeneratedValue
	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;
	}
	
	@ManyToOne(cascade=CascadeType.PERSIST,optional=false)
	@JoinColumn(name="company_id")
	public Company getCompany() {
		return company;
	}
	public void setCompany(Company company) {
		this.company = company;
	}
	
	
}

 

继承类:HourEmployee:

package com.persia.singletable;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("rate")
public class HourEmployee extends Employee {
   private Float rate;

   @Column(nullable=true)
public Float getRate() {
	return rate;
}

public void setRate(Float rate) {
	this.rate = rate;
}
   
   
}

 

SalaryEmployee:

package com.persia.singletable;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("salary")
public class SalaryEmployee extends Employee {

	private Float salary;

	@Column(nullable=true)
	public Float getSalary() {
		return salary;
	}

	public void setSalary(Float salary) {
		this.salary = salary;
	}
	
	
}

 

dao:

package com.persia.singletable;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateless
@Remote({EmployeeDAO.class})
public class EmployeeDAOBean implements EmployeeDAO {
	
	@PersistenceContext
	private EntityManager em;

	@Override
	public void deleteCompany(Integer companyId) {
		Company c=em.find(Company.class, companyId);
		em.remove(c);

	}

	@Override
	public void deleteEmployee(Integer employeeId) {
		Employee e=em.find(Employee.class, employeeId);
		e.getCompany().getEmployees().remove(e);
		e.setCompany(null);
		em.remove(e);

	}

	@Override
	public List getAllCompany() {
		Query q=em.createQuery("from Company");
		return q.getResultList();
	}

	@Override
	public void insertCompany() {
		Company c=new Company();
		c.setName("waltmart");
		SalaryEmployee se=new SalaryEmployee();
		se.setCompany(c);
		se.setName("salary-a");
		se.setSalary(9999.0f);
		
		HourEmployee he=new HourEmployee();
		he.setCompany(c);
		he.setName("hour-b");
		he.setRate(888.0f);
		Set set=new HashSet();
		set.add(se);
		set.add(he);
		c.setEmployees(set);
		em.persist(c);
		

	}

	@Override
	public void updateHourEmployee(Integer companyId, String name, float rate) {
		Company c=em.find(Company.class, companyId);
		Set set=c.getEmployees();
		Iterator it=set.iterator();
		while(it.hasNext()){
			Employee e=(Employee)it.next();
			if(e instanceof HourEmployee){
				if(e.getName().equals(name))
					((HourEmployee)e).setRate(rate);
			}
		}

	}

}

 

客户端:

package com.persia.singletabletest;

import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.persia.singletable.Company;
import com.persia.singletable.Employee;
import com.persia.singletable.EmployeeDAO;
import com.persia.singletable.HourEmployee;
import com.persia.singletable.SalaryEmployee;

public class TestSingleTable {

	/**
	 * @param args
	 * @throws NamingException 
	 */
	public static void main(String[] args) throws NamingException {
		Properties props=new Properties();
	      props.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
	      props.setProperty("java.naming.provider.url","localhost:1099");
	      props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming");
		InitialContext context=new InitialContext(props);
		try{
			EmployeeDAO edao=(EmployeeDAO)context.lookup("EmployeeDAOBean/remote");
			edao.insertCompany();
		//	edao.deleteCompany(new Integer(1));
		//	edao.deleteEmployee(new Integer(1));
		//	edao.updateHourEmployee(new Integer(1), "hour-b", 95.0f);
			List ls=edao.getAllCompany();
			if(ls!=null){
				for(int i=0;i<ls.size();i++){
					Company c=(Company)ls.get(i);
					if(c!=null){
						System.out.println("=====公司:"+c.getName()+"=====");
						Iterator it=c.getEmployees().iterator();
						while(it.hasNext()){
							Employee e=(Employee)it.next();
							if(e instanceof HourEmployee)
								System.out.println("临时工:"+((HourEmployee)e).getName()+" 薪水:"+((HourEmployee)e).getRate());
							else
								System.out.println("正式员工:"+((SalaryEmployee)e).getName()+" 薪水:"+((SalaryEmployee)e).getSalary());
						}
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}

	}

}

 

运行结果:

=====公司:waltmart=====
正式员工:salary-a 薪水:9999.0
临时工:hour-b 薪水:888.0
 

数据库:

mysql> desc company;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.03 sec)

mysql> desc employee;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| Discriminator | varchar(30)  | NO   |     | NULL    |                |
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| name          | varchar(255) | YES  |     | NULL    |                |
| rate          | float        | YES  |     | NULL    |                |
| salary        | float        | YES  |     | NULL    |                |
| company_id    | int(11)      | NO   | MUL | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+
6 rows in set (0.02 sec)

mysql> select * from company;
+----+----------+
| id | name     |
+----+----------+
|  1 | waltmart |
+----+----------+
1 row in set (0.00 sec)

mysql> select * from employee;
+---------------+----+----------+------+--------+------------+
| Discriminator | id | name     | rate | salary | company_id |
+---------------+----+----------+------+--------+------------+
| rate          |  1 | hour-b   |  888 |   NULL |          1 |
| salary        |  2 | salary-a | NULL |   9999 |          1 |
+---------------+----+----------+------+--------+------------+
2 rows in set (0.00 sec)

 

进行删除和修改:

修改

=====公司:waltmart=====
临时工:hour-b 薪水:95.0
正式员工:salary-a 薪水:9999.0

 

删除company后:

mysql> select * from employee;
Empty set (0.00 sec)

mysql> select * from company;
Empty set (0.00 sec)

 

若删除SalaryEmployee:

=====公司:waltmart=====
临时工:hour-b 薪水:888.0

 

mysql> select * from employee;
+---------------+----+--------+------+--------+------------+
| Discriminator | id | name   | rate | salary | company_id |
+---------------+----+--------+------+--------+------------+
| rate          |  2 | hour-b |  888 |   NULL |          1 |
+---------------+----+--------+------+--------+------------+
1 row in set (0.00 sec)

mysql> select * from company;
+----+----------+
| id | name     |
+----+----------+
|  1 | waltmart |
+----+----------+
1 row in set (0.00 sec)

 

------------------------------------------------------------------------------------------------------------------------------------------

SINGLE_TABLE的映射策略在所有继承策略中是最简单的,同时也是执行效率最高的,它仅仅需要对一个表进行管理和操作。在载入entity和多态连接时不需要进行任何关联,联合或子查询,因为所有的数据都存储在一个表中。

缺点是:

1.不能为所有子类的属性对应的字段定义not null 约束

2.在子类属性不是非常多的时候优先选择。(查询性能高)

转载于:https://www.cnblogs.com/cxccbv/archive/2009/01/21/1379327.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值