Hibernate学习笔记3:多表操作

这是黑马视频的学习笔记

  • 表与表的关系的复习

一对多

1.  分类和商品一类有多个商品,一个商品只属于一类

2.客户公司和联系人员工,一个客户公司有多个联系人员工,但一个联系人只属于一个客户公司

3.一对多关系的建表:通过外键建立两张表之间的关系


多对多

1.  订单和商品,一个订单含有多个商品,一个商品也会属于多个订单

2.用户和角色(职位)的关系

  • 用户:小王,小马,小宋
  • 角色:总经理,秘书,司机,保安
  • 比如小王 可以 是总经理,可以是司机
  • 比如小宋 可以 是司机,可以是秘书,可以是保安
  • 比如小马 可以 是秘书,可以是总经理
  • 一个用户里面可以由多个角色,一个角色里面可以有多个用户

一对一(很少用)

。。。。。

  • 使用hibernate完成一对多的操作

映射配置

1.以客户和联系人威力,先创建两个实体类。并且让两个实体类互相表示对方

package cn.itcast.entity;
public class LinkMan {

	private Integer lkm_id;
	private String  lkm_name;
	private String  lkm_gender;
	private  String lkm_phone;
	
	private Customer customer;
       
        public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	public Integer getLkm_id() {
		return lkm_id;
	}
	public void setLkm_id(Integer 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;
	}
	
	   
}
package cn.itcast.entity;

import java.util.HashSet;
import java.util.Set;

public class Customer {

	
	private Integer cid;
	private String custName;
	private String  custLevel;
	private String  custSource;
	private String  custPhone;
	private String custMobil;
	private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();
	
	public Integer getCid() {
		return cid;
	}
	public void setCid(Integer cid) {
		this.cid = cid;
	}
	public Set<LinkMan> getSetLinkMan() {
		return setLinkMan;
	}
	public void setSetLinkMan(Set<LinkMan> setLinkMan) {
		this.setLinkMan = setLinkMan;
	}
	public String getCustName() {
		return custName;
	}
	public void setCustName(String custName) {
		this.custName = custName;
	}
	public String getCustLevel() {
		return custLevel;
	}
	public void setCustLevel(String custLevel) {
		this.custLevel = custLevel;
	}
	public String getCustSource() {
		return custSource;
	}
	public void setCustSource(String custSource) {
		this.custSource = custSource;
	}
	public String getCustPhone() {
		return custPhone;
	}
	public void setCustPhone(String custPhone) {
		this.custPhone = custPhone;
	}
	public String getCustMobil() {
		return custMobil;
	}
	public void setCustMobil(String custMobil) {
		this.custMobil = custMobil;
	}

}

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="cn.itcast.entity.LinkMan" table="t_linkman">
      <id name="lkm_id" column="lkm_id">
         <generator class="native"></generator>
        </id>
      <property name="lkm_name" column="lkm_name"></property>
      <property name="lkm_gender" column="lkm_gender"></property>
      <property name="lkm_phone" column="lkm_phone"></property>
     
      <!--表示联系人所属客户
      name属性,因为联系人实体类使用custome对象表示,写customer名称
      class属性:customer实体类的全路径
      column属性:外键名称  -->
      <many-to-one name="customer" class="cn.itcast.entity.Customer" column="clid"></many-to-one>
      
</class>
</hibernate-mapping>

客户实体类的映射文件

<?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="cn.itcast.entity.Customer" table="t_customer">
      <id name="cid" column="cid">
         <generator class="native"></generator>
        </id>
      <property name="custName" column="custName"></property>
      <property name="custLevel" column="custLevel"></property>
      <property name="custPhone" column="custPhone"></property>
      <property name="custMobil" column="custMobil"></property>
      
      <set name="setLinkMan">
      
      <!--双向维护外键-->
      <key column="clid"></key>
      
      <one-to-many class="cn.itcast.entity.LinkMan"/>
      
      </set>
</class></hibernate-mapping>

3.创建核心配置文件,在核心配置文件中引入实体类到表的映射文件

  <!--把映射文件放到核心配置文件中,必须的  -->
   <mapping resource="cn/itcast/entity/Customer.hbm.xml"/>
   <mapping resource="cn/itcast/entity/LinkMan.hbm.xml"/>

级联保存

添加一个客户,并且为这个客户添加多个联系人

复杂写法

package cn.itcast.hibernatetest;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.entity.Customer;
import cn.itcast.entity.LinkMan;
import cn.itcast.utils.HibernateUtils;
public class HibernateOneToMany {
  //演示一对多级联保存
	@Test
	public void testAddDemo1(){
		
		SessionFactory sessionFactory=null;
		Session session=null;
		Transaction tx=null;
		try {
				
			sessionFactory=HibernateUtils.getSessionFactory();
			session=sessionFactory.openSession();
			tx=session.beginTransaction();
				
			//添加一个客户,为这个客户添加一个联系人
			//1.创建客户和联系人对象
			Customer customer=new Customer();
			customer.setCustName("传智播客");
			customer.setCustLevel("vip");
			customer.setCustSource("网络");
			customer.setCustPhone("110");
			customer.setCustMobil("999");
			
			LinkMan linkMan=new LinkMan();
			linkMan.setLkm_name("lucy");
			linkMan.setLkm_gender("男");
			linkMan.setLkm_phone("911");
			
			//2.在客户里面表示联系人,在联系人里面表示客户
			//建立客户对象和联系人对象之间的关系
			//2.1  把联系人对象放到客户对象的set集合里面
			customer.getSetLinkMan().add(linkMan);
			//2.2 把客户对象放到联系人对象里面
			linkMan.setCustomer(customer);

			//3.保存到数据库
			session.save(customer);
			session.save(linkMan);	
			tx.commit();
				
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			session.close();
			sessionFactory.close();//web项目不需要关闭
		}		
		
	}
	
}
简化写法

一般根据客户添加联系人,所以要先在客户映射文件中进行配置

<?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="cn.itcast.entity.Customer" table="t_customer">
      <id name="cid" column="cid">
         <generator class="native"></generator>
        </id>
      <property name="custName" column="custName"></property>
      <property name="custLevel" column="custLevel"></property>
      <property name="custPhone" column="custPhone"></property>
      <property name="custMobil" column="custMobil"></property>
      
      <set name="setLinkMan"  cascade="save-update">
      <!-- 一对多建表,有外键
      hibernate机制:双向维护外键,一和多的那一方都配置外键
      column属性:外键名称 -->
      <key column="clid"></key>
      <one-to-many class="cn.itcast.entity.LinkMan"/>
      
      </set>
</class>
</hibernate-mapping>
在代码的改变,只需要把联系人放到客户里面即可
package cn.itcast.hibernatetest;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.entity.Customer;
import cn.itcast.entity.LinkMan;
import cn.itcast.utils.HibernateUtils;

public class HibernateOneToMany {
  //演示一对多级联保存
	@Test
	public void testAddDemo1(){
		
		SessionFactory sessionFactory=null;
		Session session=null;
		Transaction tx=null;
		try {
				
			sessionFactory=HibernateUtils.getSessionFactory();
			session=sessionFactory.openSession();
			tx=session.beginTransaction();
				
			//添加一个客户,为这个客户添加一个联系人
			//1.创建客户和联系人对象
			Customer customer=new Customer();
			customer.setCustName("传智播客");
			customer.setCustLevel("vip");
			customer.setCustSource("网络");
			customer.setCustPhone("110");
			customer.setCustMobil("999");
			
			LinkMan linkMan=new LinkMan();
			linkMan.setLkm_name("lucy");
			linkMan.setLkm_gender("男");
			linkMan.setLkm_phone("911");
			
			
			//2  把联系人对象放到客户对象的set集合里面
			customer.getSetLinkMan().add(linkMan);
			

			//3.保存到数据库
			session.save(customer);
			session.save(linkMan);
				
				
				tx.commit();
				
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			session.close();
			sessionFactory.close();//web项目不需要关闭
		}		
		
	}
	
}

级联删除

删除一个客户,这个客户里面所有的联系人也要删除

1.配置客户映射文件的set标签

<?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="cn.itcast.entity.Customer" table="t_customer">
      <id name="cid" column="cid">
         <generator class="native"></generator>
        </id>
      <property name="custName" column="custName"></property>
      <property name="custLevel" column="custLevel"></property>
      <property name="custPhone" column="custPhone"></property>
      <property name="custMobil" column="custMobil"></property>
      
      <set name="setLinkMan"  cascade="save-update,delete">
      <!-- 一对多建表,有外键
      hibernate机制:双向维护外键,一和多的那一方都配置外键
      column属性:外键名称 -->
      
      <key column="clid"></key>
      
      <one-to-many class="cn.itcast.entity.LinkMan"/>
      
      </set>
</class>
</hibernate-mapping>

删除代码实现:

package cn.itcast.hibernatetest;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;

import cn.itcast.entity.Customer;
import cn.itcast.entity.LinkMan;
import cn.itcast.utils.HibernateUtils;

public class HibernateOneToMany {
	//演示一对多级联删除
		@Test
		public void testDelete(){
			
			SessionFactory sessionFactory=null;
			Session session=null;
			Transaction tx=null;
			try {
					
				sessionFactory=HibernateUtils.getSessionFactory();
				session=sessionFactory.openSession();
				tx=session.beginTransaction();
					
					
				//1.根据id查询客户对象
				Customer customer=session.get(Customer.class, 3);
					
				//2  调用方法删除
				session.delete(customer);
					
				tx.commit();
					
			} catch (Exception e) {
				e.printStackTrace();
				tx.rollback();
			}finally {
				session.close();
				sessionFactory.close();//web项目不需要关闭
			}		
			
		}
}

执行过程:根据id查询客户=====》根据外键值查询联系人=====》把联系人的外键设置成null====》删除联系人和客户

一对多修改操作

让一个联系人所属的客户改变成另一客户

//演示一对多级联修改
@Test
	public void testUpdate(){
				
		SessionFactory sessionFactory=null;
		Session session=null;
		Transaction tx=null;
		try {
						
			sessionFactory=HibernateUtils.getSessionFactory();
			session=sessionFactory.openSession();
			tx=session.beginTransaction();
						
				
			//1.根据id查询联系人,再根据另一个id客户对象
			Customer baidu=session.get(Customer.class, 1);
			LinkMan  linkMan=session.get(LinkMan.class, 2);
			
			//2  设置持久态对象的值
			//把联系人放到客户里面
			baidu.getSetLinkMan().add(linkMan);
			//  把客户放到联系人里面
			linkMan.setCustomer(baidu);
						
			tx.commit();
						
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			session.close();
			sessionFactory.close();//web项目不需要关闭
		}		
				
	}

inverse属性

因为hibernate双向维护外键机制,在客户和联系人里面都要维护外键,修改客户和修改联系人共产生两次外键修改。造成性能问题

解决方法:让其中一方放弃维护外键,一的那一方放弃维护

具体实现:

 <!--inverse属性的默认值是false,表示不放弃维护。改成true就表示放弃  -->
      <set name="setLinkMan" inverse="true" cascade="save-update,delete">
      <!-- 一对多建表,有外键
      hibernate机制:双向维护外键,一和多的那一方都配置外键
      column属性:外键名称 -->
      <key column="clid"></key>
      
      <one-to-many class="cn.itcast.entity.LinkMan"/>
      
      </set>
  • 使用hibernate完成多对多的操作

多对多映射配置

以用户和角色为例

1.   创建两个实体类对象,并且让两个实体类互相表示

用户实体类

package cn.itcast.manytomany;

import java.util.HashSet;
import java.util.Set;

public class User {
	
		private Integer user_id;
		private String user_name;
		private String user_password;
		
		private Set<Role> setRole=new HashSet<Role>();
		
		public Set<Role> getSetRole() {
			return setRole;
		}
		public void setSetRole(Set<Role> setRole) {
			this.setRole = setRole;
		}
		public Integer getUser_id() {
			return user_id;
		}
		public void setUser_id(Integer user_id) {
			this.user_id = user_id;
		}
		public String getUser_name() {
			return user_name;
		}
		public void setUser_name(String user_name) {
			this.user_name = user_name;
		}
		public String getUser_password() {
			return user_password;
		}
		public void setUser_password(String user_password) {
			this.user_password = user_password;
		}
}
角色实体类
package cn.itcast.manytomany;

import java.util.HashSet;
import java.util.Set;

public class Role {
		private Integer role_id;
		private String role_name;
		private String role_memo;
		
		private Set<User>  setUser=new HashSet<User>();
		
		public Set<User> getSetUser() {
			return setUser;
		}
		public void setSetUser(Set<User> setUser) {
			this.setUser = setUser;
		}
		
		public Integer getRole_id() {
			return role_id;
		}
		public void setRole_id(Integer role_id) {
			this.role_id = role_id;
		}
		public String getRole_name() {
			return role_name;
		}
		public void setRole_name(String role_name) {
			this.role_name = role_name;
		}
		public String getRole_memo() {
			return role_memo;
		}
		public void setRole_memo(String role_memo) {
			this.role_memo = role_memo;
		}
	
	
	
	
}

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="cn.itcast.manytomany.User" table="t_user">
      <id name="user_id" column="user_id">
         <generator class="native"></generator>
        </id>
      <property name="user_name" column="user_name"></property>
      <property name="user_password" column="user_password"></property>

      <!--在用户里面表示所有角色,使用set标签
       name:实体类中的角色集合变量
       table属性:第三张表的名称 -->
      <set name="setRole" table="user_role" cascade="save-update,delete">

      <!-- key标签里配置  当前映射文件在第三张表中的外键名称 -->
      <key column="userid"></key>
      <!--class:角色实体类全路径
          column:角色在第三张表中的外键名称  -->
      <many-to-many class="cn.itcast.manytomany.Role" column="roleid"/>
      
      </set>
</class>
</hibernate-mapping>

角色映射文件

 <!-- 在角色里面表示所有用户,使用set标签 -->
      <set name="setUser"  table="user_role">
      <!--角色在第三张表中的外键  -->
      <key column="roleid"></key>
      <many-to-many class="cn.itcast.manytomany.User" column="userid"/>      
      </set>

3.   核心配置文件中引入映射文件

 <mapping  resource="cn/itcast/manytomany/User.hbm.xml"/>
 <mapping  resource="cn/itcast/manytomany/Role.hbm.xml"/>

多对多级联保存

根据用户保存角色

1.在用户配置文件中使用set标签进行配置,cascade属性值为save-update

 <!--name:实体类中的角色集合变量
       table属性:第三张表的名称 -->
      <set name="setRole" table="user_role" cascade="save-update,delete">
      <!-- key标签里配置  当前映射文件在第三张表中的外键名称 -->
      <key column="userid"></key>
      <!--class:角色实体类全路径
          column:角色在第三张表中的外键名称  -->
      <many-to-many class="cn.itcast.manytomany.Role" column="roleid"/>
      
      </set>

2.代码实现

创建用户和角色对象,只要把角色放到用户里面,最终保存用户就可以了

package cn.itcast.hibernatetest;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import cn.itcast.manytomany.Role;
import cn.itcast.manytomany.User;
import cn.itcast.utils.HibernateUtils;

public class HibernateManyToMany {
      //演示多对多级联保存
	public static void main(String[] args){
		
		SessionFactory sessionFactory=null;
		Session session=null;
		Transaction tx=null;
		try {
				
			    Configuration configuration = new Configuration();
			    configuration.configure();
			    sessionFactory = configuration.buildSessionFactory();
	        
				session=sessionFactory.openSession();
				tx=session.beginTransaction();
				//添加两个用户,为每个用户添加两个角色
				//1创建对象
				User user1=new User();
				user1.setUser_name("lucy");
			    user1.setUser_password("123");
			    
			    User user2=new User();
				user2.setUser_name("Mary");
			    user2.setUser_password("456");
			    
			    Role r1=new Role();
			    r1.setRole_name("总经理");
			    r1.setRole_memo("总经理");
			    
			    Role r2=new Role();
			    r2.setRole_name("秘书");
			    r2.setRole_memo("秘书");
			    
			    Role r3=new Role();
			    r3.setRole_name("保安");
			    r3.setRole_memo("保安");
			    
			    //建立关系,把角色放到用户里面
			    //user1--r1/r2
			    user1.getSetRole().add(r1);
			    user1.getSetRole().add(r2);
			    //user2--r2/r3
			    user2.getSetRole().add(r2);
			    user2.getSetRole().add(r3);
			    
			    //保存用户
			    session.save(user1);
			    session.save(user2);
			    
				//提交事务
				tx.commit();
				
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
				//session.close();
			//web项目sessionfactory不需要关闭
			sessionFactory.close();
		}
	}
	
}

级联删除(了解)

1.在set标签里配置,cascade属性值为delete

<set name="setRole" table="user_role" cascade="save-update,delete">

2.删除用户

User user=session.get(User.class, 1);			    
session.delete(user);
			    

维护第三张表

1.用户和角色是多对多,通过维护第三张表来维护他们的关系

2.让某个用户有某个角色

先根据id查询用户和角色,再把角色放到用户里

//让某个用户有某个角色			
//让Lucy有经纪人角色				
//查询Lucy和经纪人				
 User lucy=session .get(User.class, 1);			  
  Role role=session.get(Role.class, 1);	   
 //把角色放到set集合里面
 lucy.getSetRole().add(role);				 		    

3.让某个用户没有某个角色

先根据id查询用户和角色,把用户里面的角色去掉remove

//让某个用户有某个角色			
//让Lucy有经纪人角色				
//查询Lucy和经纪人				
 User lucy=session .get(User.class, 1);			  
  Role role=session.get(Role.class, 1);	   		 		 
lucy.getSetRole().remove(role);	
				

猜你喜欢

转载自blog.csdn.net/shanshuisheng/article/details/80974734