Hibernate框架入门学习(三)

个人博客原文链接

一对多映射(重点)

编写JavaBean
  1. 1的一方
    • 保存n的一方对象的Set集合
    • hibernate框架默认的集合是set集合,集合必须要手动初始化
    • 案例:
    public class Customer {
    
    	private Long cust_id; //客户编号(主键)
    	private String cust_name;  //客户名称(公司名称)
    	private Long cust_user_id;  //负责人id
    	private Long cust_create_id; //创建人id
    	private String cust_source;  //客户信息来源
    	private String cust_industry;  //客户所属行业
    	private String cust_level; //客户级别
    	private String cust_linkman; //联系人
    	private String cust_phone; //固定电话
    	private String cust_mobile; //移动电话
    	
    	//1的一方
    	//hibernate框架默认的集合是set集合,集合必须要手动初始化
    	private Set<LinkMan> LinkMans = new HashSet<LinkMan>();
    
    	set&get...
    }
    
  2. n的一方
    • 保存1的一方的对象
    • 这个对象千万不要自己new,配置文件提供该类的全路径,hibernate框架会自己new
    • 案例:
    public class LinkMan {
    
    	private long lkm_id;
    	private String lkm_name;
    	private String lkm_gender;
    	private String lkm_phone;
    	private String lkm_mobile;
    	private String lkm_email;
    	private String lkm_qq;
    	private String lkm_position;
    	private String lkm_memo;
    	
    	//n的一方
    	//编写一个对象,千万不要自己new,配置文件提供类的全路径,hibernate框架会自己new
    	private Customer customer;
    
    	set&get...
    }
    
编写一对多的配置文件
  1. 1的一方
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 配置类和表结构的映射 -->
    	<class name="com.lousen.domain.Customer" table="cst_customer">
    		<!-- 配置id,name:JavaBean,column:表结构的字段 -->
    		<id name="cust_id" column="cust_id">
    			<!-- 主键生成策略 -->
    			<generator class="native"></generator>
    		</id>
    		
    		
    		<!-- 配置其他属性 -->
    		<property name="cust_name" column="cust_name"/>
    		<property name="cust_user_id" column="cust_user_id"/>
    		<property name="cust_create_id" column="cust_create_id"/>
    		<property name="cust_source" column="cust_source"/>
    		<property name="cust_industry" column="cust_industry"/>
    		<property name="cust_level" column="cust_level"/>
    		<property name="cust_linkman" column="cust_linkman"/>
    		<property name="cust_phone" column="cust_phone"/>
    		<property name="cust_mobile" column="cust_mobile"/>
    		
    		<!-- 配置一的一方,name:表示集合属性的名称,cascade:级联 -->
    		<set name="LinkMans" inverse="true">
    			<!-- column:外键字段 -->
    			<!-- class:集合属性的全路径 -->
    			<key column="lkm_cust_id"></key>
    			<one-to-many class="com.lousen.domain.LinkMan"/>
    		</set>
    		
    	</class>
    </hibernate-mapping>
    
  2. n的一方
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 配置类和表结构的映射 -->
    	<class name="com.lousen.domain.LinkMan" table="cst_linkman">
    		<!-- 配置id,name:JavaBean,column:表结构的字段 -->
    		<id name="lkm_id" column="lkm_id">
    			<!-- 主键生成策略 -->
    			<generator class="native"></generator>
    		</id>
    		
    		
    		<!-- 配置其他属性 -->
    		<property name="lkm_name" column="lkm_name"/>
    		<property name="lkm_gender" column="lkm_gender"/>
    		<property name="lkm_phone" column="lkm_phone"/>
    		<property name="lkm_mobile" column="lkm_mobile"/>
    		<property name="lkm_email" column="lkm_email"/>
    		<property name="lkm_qq" column="lkm_qq"/>
    		<property name="lkm_position" column="lkm_position"/>
    		<property name="lkm_memo" column="lkm_memo"/>
    		
    		<!--
    		 先配置多的一方
    		 name: 当前JavaBean中的属性
    		 class:该属性的全路径
    		 column:外键字段
    		 cascade: 级联
    		  -->
    		<many-to-one name="customer" class="com.lousen.domain.Customer" column="lkm_cust_id" cascade="save-update"></many-to-one>
    		
    	</class>
    </hibernate-mapping>
    
双向关联数据
  1. 简介
    顾客关联联系人,联系人同时也要关联顾客,两者的对象都需要保存。
  2. 双向关联数据保存
    /**
     * 双向关联保存数据(最麻烦的)
     */
    @Test
    public void run1(){
    	
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	
    	//创建一个顾客
    	Customer c1 = new Customer();
    	c1.setCust_name("张三");
    	
    	//创建两个联系人
    	LinkMan l1 = new LinkMan();
    	l1.setLkm_name("老大");
    	LinkMan l2 = new LinkMan();
    	l2.setLkm_name("老二");
    	
    	//演示双向关联
    	c1.getLinkMans().add(l1);
    	c1.getLinkMans().add(l2);		
    	l1.setCustomer(c1);
    	l2.setCustomer(c1);
    
    	//保存数据
    	session.save(c1);
    	session.save(l1);
    	session.save(l2);
    	
    	tr.commit();
    	
    }
    
级联保存
  1. 简介
    保存一方的同时可以把关联的对象也保存到数据库中,具有方向性,可以修改顾客的配置文件使顾客级联联系人,也可以修改联系人的配置文件使联系人级联顾客。
  2. 配置文件
    在配置文件添加属性cascade="save-update"即可
  3. 级联保存案例
    /**
     * 级联保存(单向关联)
     * 顾客级联联系人
     */
    @Test
    public void run2(){
    	
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	
    	//创建一个顾客
    	Customer c1 = new Customer();
    	c1.setCust_name("张三");
    	
    	//创建两个联系人
    	LinkMan l1 = new LinkMan();
    	l1.setLkm_name("老大");
    
    	LinkMan l2 = new LinkMan();
    	l2.setLkm_name("老二");
    
    	//演示级联
    	c1.getLinkMans().add(l1);
    	c1.getLinkMans().add(l2);	
    
    	//保存数据
    	session.save(c1);
    	
    	tr.commit();	
    }
    
级联删除(谨慎使用,很少使用)
  1. 简介
    • 普通的直接删除
      删除顾客以后,该顾客对应的联系人的外键那一列的值变为null
    • 级联删除
      删除顾客以后,该顾客对应的联系人的所有数据被删除
  2. 配置文件
    在配置文件添加属性cascade="delete"即可
  3. 级联删除案例
    /**
     * 级联删除
     * 同样具有方向性,也可两边都级联(很危险,相关数据全删)
     * 在联系人和顾客两边都加上级联删除
     * 删除联系人时联系人级联删除顾客,删除顾客时顾客又级联删除联系人
     */
    @Test
    public void run4(){
    	
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	
    	//删除主键为3的联系人
    	LinkMan linkman = session.get(LinkMan.class,3L);
    	session.delete(linkman);
    	
    	tr.commit();	
    }
    
孤儿删除
  1. 简介
    • 只存在于一对多
    • 在一对多的关系中,可以将一的一方认为是父方。将多的一方认为是子方。孤儿删除:在解除了父子关系的时候。将子方整条记录直接删除。
  2. 配置文件
    在配置文件<set>标签上添加属性cascade="delete-orphan"即可
    3.孤儿删除案例
    /**
     * 孤儿删除(在解除关系的基础上修改了配置文件,cascade="delete-orphan")
     * 删除整条记录
     */
    @Test
    public void run6(){
    	
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    
    	LinkMan linkman = session.get(LinkMan.class,9L);
    	Customer customer = session.get(Customer.class,9L);
    	//解除关系
    	customer.getLinkMans().remove(linkman);
    	
    	tr.commit();	
    }
    
放弃外键的维护
  1. 简介
    • 双方都维护外键的时候,会产生多余的SQL语句
    • 产生的原因:session的一级缓存中的快照机制,会让双方都更新数据库,产生了多余的SQL语句。
    • 如果不想产生多余的SQL语句,那么需要一方来放弃外键的维护
  2. 配置文件
    <set>标签上配置一个inverse="true"。默认值是false。
cascade和inverse
  1. cascade用来级联操作(保存、修改和删除)
  2. inverse用来维护外键的
  3. 两者一般不能同时存在同一个配置文件
    • inverse在一对多中必须放在1的一方,在多对多时放在少的一方
    • cascade放在inverse的另一方
    • 如果同时存在同一个配置文件,将无法对该方的外键进行保存等操作,因为这一方已经放弃了对外键的维护。

多对多映射(重点)

编写JavaBean

同一对多中多的一方
案例:

public class User {

	private Long uid;
	private String username;
	private String password;
	
	private Set<Role> roles = new HashSet<Role>();

	set&get...
}
public class Role {

	private Long rid;
	private String rname;
	
	private Set<User> users = new HashSet<User>();

	set&get...
}
编写多对多的配置文件
  1. 多-用户
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 配置类和表结构的映射 -->
    	<class name="com.lousen.domain.User" table="sys_user">
    		<!-- 配置id,name:JavaBean,column:表结构的字段 -->
    		<id name="uid" column="uid">
    			<!-- 主键生成策略 -->
    			<generator class="native"></generator>
    		</id>
    		
    		
    		<!-- 配置其他属性 -->
    		<property name="username" column="username"/>
    		<property name="password" column="password"/>
    		
    		<!--  
    		配置多对多
    		name:集合的名称
    		table:中间表的名称
    		-->
    		<set name="roles" table="sys_user_role" cascade="save-update">
    			<!-- 当前对象在中间表外键的名称 -->
    			<key column="uid" />
    			<!-- 
    			class:集合中所存对象的全路径
    			column:集合中所存对象在中间表的外键名称
    			 -->
    			<many-to-many class="com.lousen.domain.Role" column="rid"></many-to-many>
    		</set>
    		
    	</class>
    </hibernate-mapping>
    
  2. 多-角色
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 配置类和表结构的映射 -->
    	<class name="com.lousen.domain.Role" table="sys_role">
    		<!-- 配置id,name:JavaBean,column:表结构的字段 -->
    		<id name="rid" column="rid">
    			<!-- 主键生成策略 -->
    			<generator class="native"></generator>
    		</id>
    		
    		
    		<!-- 配置其他属性 -->
    		<property name="rname" column="rname"/>
    		
    		<!--  
    			配置多对多
    			name:集合的名称
    			table:中间表的名称
    		-->
    		<set name="users" table="sys_user_role" inverse="true">
    			<!-- 当前对象在中间表外键的名称 -->
    			<key column="rid" />
    			<!-- 
    				class:集合中所存对象的全路径
    				column:集合中所存对象在中间表的外键名称
    			 -->
    			<many-to-many class="com.lousen.domain.User" column="uid"></many-to-many>
    		</set>
    		
    	</class>
    </hibernate-mapping>
    
  3. 中间表
    在多对多中,只要正确配置了文件,Hibernate框架会自动生成中间表
双向关联

多对多进行双向关联的时候:必须有一方放弃外键维护权,否则会报错!!!

级联操作
  1. 简介
    同一对多
  2. 案例
    /**
     * 多对多
     * role放弃外键维护
     * 保存user时级联保存role
     */
    @Test
    public void run1(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	//创建用户
    	User u1 = new User();
    	u1.setUsername("张三");
    	User u2 = new User();
    	u2.setUsername("李四");
    	//创建角色
    	Role r1 = new Role();
    	r1.setRname("上校");		
    	Role r2 = new Role();
    	r2.setRname("下士");
    	//级联保存
    	u1.getRoles().add(r1);
    	u1.getRoles().add(r2);
    	u2.getRoles().add(r1);
    	
    	session.save(u1);
    	session.save(u2);
    	
    	tr.commit();
    }
    
维护中间表
  1. 简介
    • 在多对多中,只要正确配置了文件,Hibernate框架会自动生成中间表
    • 通过操作对应集合来操作对应的外键
  2. 案例:
    /**
     * 维护中间表
     * 通过操作集合
     */
    @Test
    public void run2(){
    	Session session = HibernateUtils.getSession();
    	Transaction tr = session.beginTransaction();
    	
    	//查询李四用户
    	User u = session.get(User.class, 2L);
    	//查询角色
    	Role r = session.get(Role.class, 2L);
    	//从中间表移除该条数据
    	u.getRoles().remove(r);
    	
    	tr.commit();
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值