• hibernate系列之四


    数据库中表之间的关系:

    一对一、一对多、多对多

    一对多的建表原则:在多的一方创建外键指向一的一方的主键;

    多对多的建表原则:创建一个中间表,中间表中至少有两个字段作为外键分别指向多对多双方的主键;

    一对一建表原则:唯一外键对应:假设一对一中的任意一方为多,在多的一方创建外键指向一的一方的主键,将外键设置为唯一

          主键对应:一方的主键作为另一方的主键;

    在hibernate中采用java对象关系描述数据表之间的关系:

    一对多的映射关系的实现案例:

    客户实体类:在hibernate系列一中已经实现点击连接查看:https://www.cnblogs.com/wang-xuan/p/9195795.html

    同时在客户实体类中添加属性:

    //一个客户对应多个联系人
    	private Set<LinkMan> linkMans = new HashSet<LinkMan>();
    public Set<LinkMan> getLinkMans() {
    		return linkMans;
    	}
    	public void setLinkMans(Set<LinkMan> linkMans) {
    		this.linkMans = linkMans;
    	}
    

    实现联系人实体类LinkMan:

    package com.itwx.hibernate.pojo;
    
    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;
    	
    	private Customer customer;
    
    	public Long getLkm_id() {
    		return lkm_id;
    	}
    
    	public void setLkm_id(Long lkm_id) {
    		this.lkm_id = lkm_id;
    	}
    
    	public String getLkm_name() {
    		return lkm_name;
    	}
    
    	public void setLkm_name(String lkm_name) {
    		this.lkm_name = lkm_name;
    	}
    
    	public String getLkm_gender() {
    		return lkm_gender;
    	}
    
    	public void setLkm_gender(String lkm_gender) {
    		this.lkm_gender = lkm_gender;
    	}
    
    	public String getLkm_phone() {
    		return lkm_phone;
    	}
    
    	public void setLkm_phone(String lkm_phone) {
    		this.lkm_phone = lkm_phone;
    	}
    
    	public String getLkm_mobile() {
    		return lkm_mobile;
    	}
    
    	public void setLkm_mobile(String lkm_mobile) {
    		this.lkm_mobile = lkm_mobile;
    	}
    
    	public String getLkm_email() {
    		return lkm_email;
    	}
    
    	public void setLkm_email(String lkm_email) {
    		this.lkm_email = lkm_email;
    	}
    
    	public String getLkm_qq() {
    		return lkm_qq;
    	}
    
    	public void setLkm_qq(String lkm_qq) {
    		this.lkm_qq = lkm_qq;
    	}
    
    	public String getLkm_position() {
    		return lkm_position;
    	}
    
    	public void setLkm_position(String lkm_position) {
    		this.lkm_position = lkm_position;
    	}
    
    	public String getLkm_memo() {
    		return lkm_memo;
    	}
    
    	public void setLkm_memo(String lkm_memo) {
    		this.lkm_memo = lkm_memo;
    	}
    
    	public Customer getCustomer() {
    		return customer;
    	}
    
    	public void setCustomer(Customer customer) {
    		this.customer = customer;
    	}
    	
    }
    

     配置LinkMan.hbm.xml的映射文件

    <?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.itwx.hibernate.pojo.LinkMan" table="linkman">
    		<id name="lkm_id" column="lkm_id">
    			<generator class="native" />
    		</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" />
    		<!-- 配置关联对象 -->
    		<!--  
    			many-to-one:代表多对一:
    				name属性:在实体类中的属性:一的一方的对象的名称;
    				class属性:一的一方的类的全路径
    				column:表中的外键,在一的一方中配置的外键;
    		-->
    		<many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
    			column="lkm_cust_id" />
    	</class>
    </hibernate-mapping>
    

     核心配置文件hibernate.cfg.xml

    <!-- 配置加载映射文件:全路径-->
    			<mapping resource="com/itwx/hibernate/pojo/Customer.hbm.xml"/>
    			<mapping resource="com/itwx/hibernate/pojo/LinkMan.hbm.xml"/>
    

     Customer.hbm.xml配置文件添加一对多的关系映射配置

    <!-- 配置多一之间的映射关系 -->
        	<!-- 
        		set标签:name属性:在实体类中的属性,指多的一方的集合的属性名称
        		key标签:column:多的一方的外键的名称
        		one-to-many标签:class属性:多的一方的类的全路径
        	-->
    		<set name="linkMans">
    			<key column="lkm_cust_id" />
    			<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
    		</set>
    

     测试类中进行测试一对多的关系映射

    @Test
    	public void test4() {
    		// 获取当前与线程绑定的session
    		Session session = HibernateUtils.getCurrentSession();
    		// 开启事务
    		Transaction transaction = session.beginTransaction();
    		// 创建关系对象
    		Customer customer = new Customer();// 此处可以使用带参构造方法
    		customer.setCust_name("张三");
    		customer.setCust_source("产品");
    
    		LinkMan linkMan1 = new LinkMan();
    		linkMan1.setLkm_name("周芷若");
    		linkMan1.setLkm_phone("1223445");
    		LinkMan linkMan2 = new LinkMan();
    		linkMan2.setLkm_name("张无忌");
    		linkMan2.setLkm_gender("男");
    		// 建立关系
    		/**
    		 * 首先获取到set集合对象,然后才能进行添加元素; 所以先调用getXXX()方法获取对象,然后add
    		 */
    		// 客户关联联系人
    		customer.getLinkMans().add(linkMan1);
    		customer.getLinkMans().add(linkMan2);
    		// 联系人关联客户
    		linkMan1.setCustomer(customer);
    		linkMan2.setCustomer(customer);
    		// 执行操作
    		session.save(linkMan1);
    		session.save(linkMan2);
    		session.save(customer);
    		// 提交事务
    		transaction.commit();
              //执行结果 /** * Hibernate: insert into linkman (lkm_name, lkm_gender, lkm_phone, * lkm_mobile, lkm_email, lkm_qq, lkm_position, lkm_cust_id) values (?, * ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into linkman (lkm_name, * lkm_gender, lkm_phone, lkm_mobile, lkm_email, lkm_qq, lkm_position, * lkm_cust_id) values (?, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into * customer (cust_name, cust_source, cust_industry, cust_level, * cust_phone, cust_mobile) values (?, ?, ?, ?, ?, ?) Hibernate: update * linkman set lkm_name=?, lkm_gender=?, lkm_phone=?, lkm_mobile=?, * lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=? where lkm_id=? * Hibernate: update linkman set lkm_name=?, lkm_gender=?, lkm_phone=?, * lkm_mobile=?, lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=? * where lkm_id=? Hibernate: update linkman set lkm_cust_id=? where * lkm_id=? Hibernate: update linkman set lkm_cust_id=? where lkm_id=? */ }

     级联操作:

    指在主控方执行保存、更新和删除操作时,其关联(被控方)也执行相同操作。在映射文件中通过对cascade属性的设置来控制是否对关联对象采用级联操作,级联操作对各种关联关系都是有效的;

    级联具有方向性:在保存一的一方级联多的一方和在多的一方可以级联一的一方;

    在映射文件中配置cascade=“save-update”;

    级联删除和级联保存、更新:谁是主控方,则可以在映射文件中配置cascade=“delete、save-update”,也可以同时配置;

    级联删除:在set标签中配置cascade=“delete”或者在mony-to-one中配置cascade属性;

    <many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
    			column="lkm_cust_id" cascade="save-update"  />
    

     或者

    <set name="linkMans" cascade="delete,save-update" >
    			<key column="lkm_cust_id" />
    			<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
    		</set>
    

    防止SQL语句冗余:双向维护关系,持久态对象可以自动更新数据库,更新客户的时候会修改一次外键,更新联系人的时候会修改一次外键,所以会产生SQL语句冗余;

    解决方案:一方放弃外键的维护,通常交给多的一方去维护,所以一的一方就需要放弃维护,即需要配置inverse=“true”;

    <set name="linkMans" cascade="delete,save-update" inverse="true">
                <key column="lkm_cust_id" />
                <one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
            </set>
  • 相关阅读:
    Infosec institute n00bs CTF writeup
    CTF学习之CODE
    ThinkPHP函数详解:C方法
    流程控制的替代语法
    Jquery DOM
    YII2 请求(request)
    YII2 运行概述(Overview)
    YII2 小部件(widgets)
    YII2 过滤器 filters
    YII2 随笔 视图最佳实践
  • 原文地址:https://www.cnblogs.com/wx_blog/p/9199286.html
Copyright © 2020-2023  润新知