一、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;
}
}
<?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>
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方法都是应该有程序员完成添加