Hibernate学习笔记 -- day08 注解含义、一对多关系映射

一、表关系原则

1、对象关系映射(ORM)建立表关系映射应遵循以下步骤

第一步:明确两张表之间的关系

第二步:在数据库中建立两张表之间的关系

第三步:在实体类中描述出两个实体之间的关系

第四步:在映射配置(注解/XML)中建立两个实体之间的关系

二、表关系映射中注解含义

Hibernate学习笔记 -- day08 注解含义、一对多关系映射_第1张图片

三、一对多关联关系示例

1、以客户的联系人为例

四、明确关系

1、一家公司可以包含多个员工,多个员工可能属于同一家公司

五、数据库中建立表关系

1、一对多表关系,在数据库中靠的是外键约束。 

2、我们习惯把一对多中一的方称之为:主表。把多的一方称之为:从表。

3、外键:

      指的是从表中有一列,它的取值来源于主表的主键。

      我们就把从表中的这一列叫外键。

六、实体类中描述出两个实体之间的关系

1、主表实体中包含的是从表实体的一个集合引用,集合的元素都是从表的实体。

/**
 * 客户的实体
 * @author zhy
 * 注解都是JPA规范的
 */
@Entity
@Table(name="cst_customer")
public class Customer implements Serializable {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="cust_id")
	private Long custId;
	@Column(name="cust_name")
	private String custName;
	@Column(name="cust_source")
	private String custSource;
	@Column(name="cust_industry")
	private String custIndustry;
	@Column(name="cust_level")
	private String custLevel;
	@Column(name="cust_address")
	private String custAddress;
	@Column(name="cust_phone")
	private String custPhone;
	
	//一对多关系映射:一个客户可以包含多个联系人 
	@OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE) 
	private Set linkmans = new HashSet(0);

2、从表实体中包含的是主表实体的一个对象引用。

/**
 * 联系人的实体
 * @author zhy
 *
 */
@Entity
@Table(name="cst_linkman")
public class LinkMan implements Serializable {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="lkm_id")
	private Long lkmId;
	@Column(name="lkm_name")
	private String lkmName;
	@Column(name="lkm_gender")
	private String lkmGender;
	@Column(name="lkm_phone")
	private String lkmPhone;
	@Column(name="lkm_mobile")
	private String lkmMobile;
	@Column(name="lkm_email")
	private String lkmEmail;
	@Column(name="lkm_position")
	private String lkmPosition;
	@Column(name="lkm_memo")
	private String lkmMemo;
	
	
	//多对一关系映射:多个联系人对应一个客户
	@ManyToOne(targetEntity=Customer.class)
	@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
	private Customer customer;

七、在配置映射中体现两个实体之间的关系

1、注解的方式配置关联关系

客户实体

	//一对多关系映射:一个客户可以包含多个联系人 
	@OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE) 
	private Set linkmans = new HashSet(0);

联系人实体

	//多对一关系映射:多个联系人对应一个客户
	@ManyToOne(targetEntity=Customer.class)
    //参数:1、从表中外间字段的名称,2、主表的主键
	@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
	private Customer customer;

2、xml方式配置关联关系

客户映射文件




	
		
			
		
		
		
		
		
		
		
		

		
			
			
		
	

联系人映射文件




	
		
			
		
		
		
		
		
		
		
		
		
		

		
	

八、一对多关系的操作

1、保存

注意:明确主表和从表保存顺序不同产生的不同结果

	/**
	 * 保存操作
	 * 需求:
	 * 	1、创建一个客户,创建一个联系人
	 * 	2、建立客户和联系人的双向关联关系
	 * 	3、保存客户和联系人
	 * 问题:
	 * 	我们先保存谁呢?
	 *  测试:
	 *  	我们先保存的联系人(从表),再保存主表。
	 *  	会产生3条SQL语句。其中有两条insert,一条update。
	 *  	我们明明只需要两条insert。
	 *  原因:
	 *  	快照机制
	 *  保存原则:
	 *  	先保存主表实体,再保存从表实体
	 * 	
	 */
	@Test
	public void test1(){
		//准备数据
		Customer c = new Customer();
		c.setCustName("TBD云集中心");
		c.setCustIndustry("商业办公");
		c.setCustLevel("VIP客户");
		c.setCustSource("电话");
		c.setCustAddress("昌平区北七家");
		c.setCustPhone("010-34343548");
		
		LinkMan l = new LinkMan();
		l.setLkmName("TBD联系人");
		l.setLkmGender("male");
		l.setLkmMobile("13811111111");
		l.setLkmPhone("010-34593498");
		l.setLkmPosition("商务部员工");
		l.setLkmEmail("[email protected]");
		l.setLkmMemo("普通员工");
		
		//建立双向关联关系
		c.getLinkmans().add(l); 
		l.setCustomer(c);
		
		
		Session s = HibernateUtil.getCurrentSession();
		Transaction tx = s.beginTransaction();
		//保存操作
//		s.save(l);//联系人实体状态转变:变成持久态		联系人的快照产生了:关联的客户OID是null
//		s.save(c);//客户实体状态转变:变成持久态
		
		s.save(c);
		Customer c1 = s.get(Customer.class, c.getCustId());
		System.out.println(c1);
		s.save(l);
		
		tx.commit();
	}

2、更新操作

注意:想要在更新主表的时候级联保存(更新)从表,需要在实体类上加上级联操作的注解:cascade

	//一对多关系映射:一个客户可以包含多个联系人 
	@OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE) 
	private Set linkmans = new HashSet(0);

	/**
	 * 更新操作
	 * 需求:
	 * 	1、根据id查询一个客户
	 * 	2、创建一个新的联系人
	 *  3、为查询出来的客户分配新的联系人(建立联系人和客户的关联关系)
	 *  4、更新客户
	 * 问题:
	 * 	当我们更新时,不会有任何更新的操作。新创建的联系人没有给客户分配成功。
	 * 解决:
	 * 	使用配置的方式,告知Hiernate框架,为我们进行级联操作。
	 * 	告知的方式:
	 * 		在注解上使用注解的属性。
	 */
	@Test
	public void test2(){
		//准备数据
		LinkMan l = new LinkMan();		//瞬时态对象
		l.setLkmName("TBD联系人test3");
		l.setLkmGender("male");
		l.setLkmMobile("13811111111");
		l.setLkmPhone("010-34593498");
		l.setLkmPosition("商务部员工");
		l.setLkmEmail("[email protected]");
		l.setLkmMemo("普通员工");
		
		Session s = HibernateUtil.getCurrentSession();
		Transaction tx = s.beginTransaction();
		//根据id查询客户
		Customer c1 = s.get(Customer.class, 1L);
		//建立客户和联系人的关联关系
		c1.getLinkmans().add(l);//联系人是瞬时态
		l.setCustomer(c1);//联系人是瞬时态
		//更新客户
		s.update(c1);//我们希望的是在此行,hibernate框架能帮我们做两件事。(先把临时态对象转成持久态,然后再去更新)
		tx.commit();
	}

3、删除操作

	/**
	 * 删除操作:
	 * 	删除从表数据:
	 * 		随便删。
	 *  删除主表数据:
	 *  	需要看看有没有从表的引用:
	 *  		有从表引用:
	 *  			一般情况下不能删。
	 *  			要想删除的话:需要使用级联删除。
	 *  				它的作用就是:先把从表的数据删了,再删除主表数据。
	 *  				实际开发中一定要慎用!
	 *  		没有从表引用:
	 *  			随便删
	 */
	@Test
	public void test3(){
		Session s = HibernateUtil.getCurrentSession();
		Transaction tx = s.beginTransaction();
		//根据id查询客户
		Customer c1 = s.get(Customer.class, 1L);
		//删除id为1的客户
		s.delete(c1);
		tx.commit();
	}


你可能感兴趣的:(ssh框架)