hibernate之关联映射

1.集合映射

      需求:用户购买,填写地址,一个用户可以对应多个地址

首先是javabean设计

public class User {

	private int userId;
	private String userName;
	// 一个用户,对应的多个地址
	private Set<String> address;
	private List<String> addressList = new ArrayList<String>(); 
	//private String[] addressArray; // 映射方式和list一样     <array name=""></array>
	private Map<String,String> addressMap = new HashMap<String, String>();
	
}

然后是xml配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.itcast.a_collection">
	
	<class name="User" table="t_user">
		<id name="userId" column="id">
			<generator class="native"></generator>
		</id>	
		<property name="userName"></property>
		
		<!-- 
			set集合属性的映射
				name 指定要映射的set集合的属性
				table 集合属性要映射到的表
				key  指定集合表(t_address)的外键字段
				element 指定集合表的其他字段
					type 元素类型,一定要指定
		 -->
		 <set name="address" table="t_address">
		 	<key column="uid"></key>
		 	<element column="address" type="string"></element>
		 </set>
		 
		 <!-- 
		 	list集合映射
		 		list-index  指定的是排序列的名称 (因为要保证list集合的有序)
		  -->
		  <list name="addressList" table="t_addressList">
		  	  <key column="uid"></key>
		  	  <list-index column="idx"></list-index>
		  	  <element column="address" type="string"></element>
		  </list>
		  
		  <!-- 
		  	map集合的映射
		  		key  指定外键字段
		  		map-key 指定map的key 
		  		element  指定map的value
		   -->
		  <map name="addressMap" table="t_addressMap">
		  	<key column="uid"></key>
		  	<map-key column="shortName" type="string" ></map-key>
		  	<element column="address" type="string" ></element>
		  </map>
           </class>
</hibernate-mapping>

保存方法相关代码:

// 保存set
	@Test
	public void testSaveSet() throws Exception {
		Session session = sf.openSession();
		session.beginTransaction();
		
		//-- 保存
		Set<String> addressSet = new HashSet<String>();
		addressSet.add("广州");
		addressSet.add("深圳");
		// 用户对象
		User user = new User();
		user.setUserName("Jack");
		user.setAddress(addressSet);
		
		// 保存
		session.save(user);
		
		session.getTransaction().commit();
		session.close();
	}
	
	// 保存list/map
	@Test
	public void testSaveList() throws Exception {
		Session session = sf.openSession();
		session.beginTransaction();
		User user = new User();
		user.setUserName("Tom");
//		// 用户对象  --  list
//		user.getAddressList().add("广州");
//		user.getAddressList().add("深圳");
//		// 保存
//		session.save(user);
		
		// 用户对象  --  Map
		user.getAddressMap().put("A0001", "广州");
		user.getAddressMap().put("A0002", "深圳");
		
		// 保存
		session.save(user);
		
		session.getTransaction().commit();
		session.close();
	}


2.关联映射
  

需求1

         部门与员工

                     一个部门有多个员工;       【一对多】

                     多个员工,属于一个部门    【多对一】

需求2

         项目与开发员工

                   一个项目,有多个开发人员!

                   一个开发人员,参与多个项目!   【多对多】

 

public class Dept {

	private int deptId;
	private String deptName;
	// 【一对多】 部门对应的多个员工
	private Set<Employee> emps = new HashSet<Employee>();
	

这里省略get和set方法代码

public class Employee {

	private int empId;
	private String empName;
	private double salary;
	// 【多对一】员工与部门
	private Dept dept;

然后是xml配置

Dept.hbm.xml 

<hibernate-mapping package="cn.itcast.b_one2Many">
	
	<class name="Dept" table="t_dept">
		<id name="deptId">
			<generator class="native"></generator>   <span style="color:#ff0000;">native表示框架会自动根据数据库底层选择对应的自增方式</span>
		</id>	
		<property name="deptName" length="20"></property>
		
		<!-- 
			一对多关联映射配置  (通过部门管理到员工)
			Dept 映射关键点:
			1.  指定 映射的集合属性: "emps"
			2.  集合属性对应的集合表: "t_employee"
			3.  集合表的外键字段   "t_employee. dept_id"
			4.  集合元素的类型
			
		 -->
		 <set name="emps">   <!-- table="t_employee" -->
		 	 <key column="dept_id"></key>
		 	 <one-to-many class="Employee"/>如果配置文件和实体类不在一个包下,class后要加上包名
		 </set>
		 
		 
	</class>
	

</hibernate-mapping>

Employee.hbm.xml,两处外键字段要相同都是dept_id

<hibernate-mapping package="cn.itcast.b_one2Many">
	
	<class name="Employee" table="t_employee">
		<id name="empId">
			<generator class="native"></generator>
		</id>	
		<property name="empName" length="20"></property>
		<property name="salary" type="double"></property>
		
		<!-- 
			多对一映射配置
			Employee 映射关键点:
			1.  映射的部门属性  :  dept
			2.  映射的部门属性,对应的外键字段: dept_id
			3.  部门的类型
		 -->
		 <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>
		 
	</class>
	

</hibernate-mapping>

测试

public class App {
	
	private static SessionFactory sf;<span style="color:#ff0000;">静态方便类直接调用,而且只加载一次</span>
	static {
		sf = new Configuration()
			.configure()
			.addClass(Dept.class)   
			.addClass(Employee.class)   // 测试时候使用
			.buildSessionFactory();
	}

	// 保存, 部门方 【一的一方法操作】
	@Test
	public void save() {
		
		Session session = sf.openSession();
		session.beginTransaction();
		
		// 部门对象
		Dept dept = new Dept();
		dept.setDeptName("应用开发部");
		// 员工对象
		Employee emp_zs = new Employee();
		emp_zs.setEmpName("张三");
		Employee emp_ls = new Employee();
		emp_ls.setEmpName("李四");
		// 关系
		dept.getEmps().add(emp_zs);
		dept.getEmps().add(emp_ls);

		// 保存
		session.save(emp_zs);
		session.save(emp_ls);
		session.save(dept); // 保存部门,部门下所有的员工  
		
		session.getTransaction().commit();
		session.close();
		/*
		 *  结果
		 *  Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			Hibernate: insert into t_dept (deptName) values (?)
			Hibernate: update t_employee set deptId=? where empId=?    维护员工引用的部门的id
			Hibernate: update t_employee set deptId=? where empId=?
		 */
	}
	// 【推荐】 保存, 部员方 【多的一方法操作】
	@Test
	public void save2() {
		
		Session session = sf.openSession();
		session.beginTransaction();
		
		// 部门对象
		Dept dept = new Dept();
		dept.setDeptName("综合部");
		// 员工对象
		Employee emp_zs = new Employee();
		emp_zs.setEmpName("张三");
		Employee emp_ls = new Employee();
		emp_ls.setEmpName("李四");
		// 关系<span style="color:#ff0000;">,不要忘记添加关系维护</span>
		emp_zs.setDept(dept);
		emp_ls.setDept(dept);
		
		
		// 保存
		session.save(dept); // 先保存一的方法,<span style="color:#ff0000;">注意session保存的顺序</span>
		session.save(emp_zs);
		session.save(emp_ls);// 再保存多的一方,关系回自动维护(映射配置完)
		
		session.getTransaction().commit();
		session.close();
		/*
		 *  结果
		 *  Hibernate: insert into t_dept (deptName) values (?)
			Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			少生成2条update  sql
		 */
	}
	
}

总结:

  在一对多与多对一的关联关系中,保存数据最好的通过多的一方来维护关系,这样可以减少update语句的生成,从而提高hibernate的执行效率!



Inverse属性



Inverse属性,是在维护关联关系的时候起作用的。


      表示控制权是否转移。(在一的一方起作用)


 


Inverse , 控制反转。


Inverse = false  不反转;   当前方有控制权


                   True  控制反转; 当前方没有控制权

除了对获取数据没有影响,对于保存数据,解除关联关系,删除数据都有影响。


cascade属性

cascade 表示级联操作  【可以设置到一的一方或多的一方】

         none         不级联操作, 默认值

         save-update     级联保存或更新

         delete                 级联删除

         save-update,delete    级联保存、更新、删除

         all                 同上。级联保存、更新、删除



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值