Hibernate关联关系之一对多

Hibernate关联关系之一对多
1.一对多关联
1的一方存储Set集合;多的一方存储1方的对象。
注意:Hibernate中的mapping数据库的主外键约束没有绝对的联系。即使数据库中不设置主外键约束,同样可以在hibernate中设置一对多,或多对一,多对多的映射关系,只要你的表符合外键关联的设计要求就可以。

一对多可以不用放弃维护,多对多一定要有一方放弃维护,否则报错。

inverse维护关系
用于指示本方是否参与维护关系,设置为true表示不维护,设置false表示维护,默认为false。
本属性一般用于一对多关系中一端,并设置为false。

案例:一个部门有多名员工

数据库表结构
#部门表
CREATE TABLE T_DEPT(
DEPT_ID INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘部门ID’,
DEPT_NAME VARCHAR(30) COMMENT ‘部门名称’
);
#员工表
CREATE TABLE T_EMP(
EMP_ID INT PRIMARY KEY AUTO_INCREMENT COMMENT ‘员工ID’,
EMP_NAME VARCHAR(20) COMMENT ‘员工姓名’,
SALARY FLOAT COMMENT ‘薪水’,
DEPT_ID INT COMMENT ‘部门ID’
#注意:这里DEPT_ID部门ID并没有创建外键关系,这里可以创建,也可以不创建,Hibernate对象关系映射中可指定
);

持久化类:

//部门类
public class Dept{
private int deptID;
private String deptName;
//当前为1的一方,创建Set集合用于存储多方的Emp对象
private Set<Emp> empSet = new HashSet<Emp>(); 
    //构造函数和getter/setter方法
}
//员工类
public class Emp{
private int empId;            //员工的编号
    private String empName;      //员工的名称
private double salary;        //员工的薪资
private Dept dept;             //员工和部门的关系
//省略构造函数和getter/setter方法
}

映射文件:

//Dept.hbm.xml对象关系映射文件
<hibernate-mapping package="com.zkgin.pojo">
    <class name="Dept" table="T_DEPT">
        <id name="deptId" column="DEPT_ID">
            <generator class="native" />
        </id>
        <property name="deptName" column="DEPT_NAME" />
        <!--映射关系:部门vs员工(一对多)
            <set>表示当前类中保存多的set集合; 
            name指定映射的集合的属性名:empSet;
            table指定empSet对应的集合表,如T_EMP,即set集合中保存对象映射的表;
            cascade指级联保存、修改、删除,可选项:all,save-update,delete等
            fetch指抓取,join表示把关联的对象全部抓取出来
            Key指集合表的外键字段(说白了就是多中的外键名,这需要一方和多方共同维护)。
            One-to-many指一对多,class指集合中对象类型
-->
        <set name="empSet" table="T_EMP" cascade="save-update" fetch="join">
            <key column="DEPT_ID" />
            <one-to-many class="Emp" />
        </set>
    </class>
</hibernate-mapping>
// Emp.hbm.xml映射文件:
<hibernate-mapping package="com.zkgin.pojo">
    <class name="Emp" table="T_EMP">
        <id name="empId" column="EMP_ID">
            <generator class="native" />
        </id>
        <property name="empName" column="EMP_NAME" />
        <property name="salary" column="SALARY" />
        <!--映射关系:部门vs员工(一对多)
            name对应Email类中一方的属性:user
	       class对应一方的属性对应的类
            column表示一和多方共同维护的外键名称(说白了就是多中的外键名,这需要一方和多方共同维护)
-->
        <many-to-one name="dept" class="Dept" column="DEPT_ID"></many-to-one>
    </class>
</hibernate-mapping>

注意:一对多,一的一方持久化类放Set集合,多的一方持久化类放对象。

添加映射文件:

	<mapping resource="com/zking/pojo/Dept.hbm.xml" />
	<mapping resource="com/zking/pojo/Emp.hbm.xml" />

CURD操作:

public class HibernateTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;

@Before
public void init(){
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}

@After
public void destory(){
transaction.commit();
session.close();
sessionFactory.close();
}

@Test
public void TestSave(){
//1. 一对多添加操作

//(1)初始化部门对象
Dept dept = new Dept();
dept.setDeptName("开发部");
//(2)初始化员工对象
Employee emp1 = new Employee();
emp1.setEmpName("张三1");
Employee emp2 = new Employee();
emp2.setEmpName("李四2");
//(3)为部门对象的Set集合中添加员工
dept.getEmps().add(emp1);
dept.getEmps().add(emp2);
//(4)为员工对象添加部门对象
emp1.setDept(dept);
emp2.setDept(dept);
//(5)保存一得一方
session.save(dept);
**注意1**:如果Dept.hbm.xml的关联关系中没有配置级联cascade=”save-update”,则除了保存一得一方外,还要保存多的一方,即还要添加如下两行代码:
session.save(emp1);
session.save(emp2);

**注意2**:session对象提供的saveOrUpdate()方法功能比save()要强大,即可当保存使用,也可当更新使用
session.saveOrUpdate(dept);
}


@Test
public void TestDel(){
   /**
*  级联删除:即删除一个Dept对象,会将其对应的所有Emp删除
*  1. 先修改一方的映射文件:Dept.hbm.xml
*  <set name="empSet" cascade="delete,save-update">//多个以逗号分隔:save-update,delete
*  2. 执行删除操作
*/
//根据主键ID查找对象
Dept dept = session.get(Dept.class, 2);
//删除对象
session.delete(dept);
}

@Test
public void TestUpdate(){
    // 需求:修改主键为2的部门的员工属性
		// 1. 根据主键查询Dept对象
		Dept dept = session.get(Dept.class, 2);
		// 2. 根据主键查询Emp对象
		Emp emp = session.get(Emp.class, 1);
        // 3. 设置Emp员工对象的属性值
        emp.setEmpName(“刘涛”);
        dept.getEmpName().add(emp);
        
注意:如果修改两次,是因为hibernate中双向维护外键,在Dept和Emp里面都需要维护外键,修改Dept时修改一次外键,修改Emp时也修改一次外键,造成效率问题
        解决方式:双向维护的情况下,让其中一方放弃外键的维护。谁放弃?外键在哪个表,我们就让哪一方来维护。
        具体实现:在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性。
        -------Dept.hbm.xml--------------------------------
		<set name="empSet" cascade=”save-update” inverse="true">  //false不放弃true放弃
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值