Hibernate4从入门到精通七——————ORM之Many和One的关系


一、ManyToOne单向


1、在包org.zttc.itat.model下新建:

Student.java

package org.zttc.itat.model;

public class Student {
	private int id;
	private String name;
	private String no;
	private Classroom classroom;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getNo() {
		return no;
	}
	public void setNo(String no) {
		this.no = no;
	}
	public Classroom getClassroom() {
		return classroom;
	}
	public void setClassroom(Classroom classroom) {
		this.classroom = classroom;
	}
}


Student.hbm.xml

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

<hibernate-mapping package="org.zttc.itat.model">
    <class name="Student" table="t_stu">
        <id name="id">
          	<generator class="native"/>
        </id>
        <property name="name"/>
        <property name="no"/>
        <!-- many-to-one用来映射多对一,name表示对象中的属性名称 ,column用来表示外键的名称-->
        <many-to-one name="classroom" column="cid"/>
    </class>
</hibernate-mapping>


Classroom.java

package org.zttc.itat.model;


public class Classroom {
	private int id;
	private String name;
	private int grade;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getGrade() {
		return grade;
	}
	public void setGrade(int grade) {
		this.grade = grade;
	}
	
	
}


Classroom.hbm.xml

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

<hibernate-mapping package="org.zttc.itat.model">
    <class name="Classroom" table="t_cla">
        <id name="id">
          	<generator class="native"/>
        </id>
        <property name="name"/>
        <property name="grade"/>
    </class>
</hibernate-mapping>


2、在org.zttc.itat.test包下新建

TestMany2One.java

package org.zttc.itat.test;

import org.hibernate.Session;
import org.junit.Test;
import org.zttc.itat.model.Classroom;
import org.zttc.itat.model.Student;
import org.zttc.itat.util.HibernateUtil;

public class TestMany2One {
	
	@Test
	public void testAdd01() {
		Session session = null;
		try {
			session = HibernateUtil.openSession();
			session.beginTransaction();
			//先添加1
			Classroom c = new Classroom();
			c.setGrade(2012);
			c.setName("计算机网络技术");
			session.save(c);
			Student stu1 = new Student();
			stu1.setName("猪八戒");
			stu1.setNo("001");
			stu1.setClassroom(c);
			session.save(stu1);
			Student stu2 = new Student();
			stu2.setName("孙悟空");
			stu2.setNo("002");
			stu2.setClassroom(c);
			session.save(stu2);
			
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateUtil.close(session);
		}
	}
	
	@Test
	public void testAdd02() {
		Session session = null;
		try {
			session = HibernateUtil.openSession();
			session.beginTransaction();
			//先添加多
			Student stu1 = new Student();
			stu1.setName("沙僧");
			stu1.setNo("003");
			session.save(stu1);
			Student stu2 = new Student();
			stu2.setName("唐僧");
			stu2.setNo("004");
			session.save(stu2);
			Classroom c = new Classroom();
			c.setGrade(2012);
			c.setName("计算机应用技术");
			session.save(c);
			//此时还会发两条update
			stu1.setClassroom(c);
			stu2.setClassroom(c);
			//最佳实践:一定要先添加一的一方,之后在添加多的一方
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateUtil.close(session);
		}
	}
	
	@Test
	public void testLoad01() {
		Session session = null;
		try {
			session = HibernateUtil.openSession();
			session.beginTransaction();
			Student stu = (Student)session.load(Student.class, 1);
			//此时仅仅只是发一条sql
			System.out.println(stu.getName());
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateUtil.close(session);
		}
	}
	
	@Test
	public void testLoad02() {
		Session session = null;
		try {
			session = HibernateUtil.openSession();
			session.beginTransaction();
			Student stu = (Student)session.load(Student.class, 1);
			
			//先发sql取Student对象,因为Student的关联对象Classroom也是延迟加载的,
			//所以会再发一条sql来取Classroom,一共两条sql。用抓取策略会优化,后面会讲。
			System.out.println(stu.getClassroom().getName());
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateUtil.close(session);
		}
	}
}


3、分别运行里面的方法,会得出结论:

                       先添加1的一方,再添加多的一方。


4.1运行测试函数

@Test
	public void testAdd03() {
		Session session = null;
		try {
			session = HibernateUtil.openSession();
			session.beginTransaction();
			Classroom c = new Classroom();
			c.setGrade(2012);
			c.setName("计算机信息管理");
			//此时classroom没有存储,所以在添加student的时候没有外键,会抛出异常
			Student stu1 = new Student();
			stu1.setName("如来");
			stu1.setNo("005");
			session.save(stu1);
			Student stu2 = new Student();
			stu2.setName("观音");
			stu2.setNo("006");
			session.save(stu2);
			stu1.setClassroom(c);
			stu2.setClassroom(c);
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateUtil.close(session);
		}
	}

会抛出异常,因为Classroom对象没有存储,添加Student的时候没有外键。

4.2改变Student.hbm.xml如下

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

<hibernate-mapping package="org.zttc.itat.model">
    <class name="Student" table="t_stu">
        <id name="id">
          	<generator class="native"/>
        </id>
        <property name="name"/>
        <property name="no"/>
        <!-- many-to-one用来映射多对一,name表示对象中的属性名称 ,column用来表示外键的名称-->
        <!-- 当设置了cascade的时候,会自动完成关联,如果添加时没有关联对象,会自动创建一个关联对象-->       
        <many-to-one name="classroom" column="cid" cascade="all"/>
    </class>
</hibernate-mapping>

再运行测试函数如下:

Hibernate: insert into t_stu (name, no, cid) values (?, ?, ?)
Hibernate: insert into t_stu (name, no, cid) values (?, ?, ?)
Hibernate: insert into t_cla (name, grade) values (?, ?)
Hibernate: update t_stu set name=?, no=?, cid=? where id=?
Hibernate: update t_stu set name=?, no=?, cid=? where id=?

成功添加进入数据库。


5、运行测试函数

@Test
	public void testDelete01() {
		Session session = null;
		try {
			session = HibernateUtil.openSession();
			session.beginTransaction();
			Student stu = (Student)session.load(Student.class, 7);
			session.delete(stu);
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			if(session!=null) session.getTransaction().rollback();
		} finally {
			HibernateUtil.close(session);
		}
	}

结果:抛出异常     

Cannot delete or update a parent row: a foreign key constraint fails (`itat_hibernate`.`t_stu`, CONSTRAINT `FK68F93E9F84B0E37` FOREIGN KEY (`cid`) REFERENCES `t_cla` (`id`))

,为什么呢?  因为删除学生为7的字段包含外键cid。也不能更新。


结论:如果没有特殊情况不要使用cascade,特别注意,可能使用cascade的地方一般都是一的一方进行删除时使用
        特殊需求才会使用cascade的add,正常情况add方法都是应该有程序员完成添加


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值