Hibenate的单向关联映射(注解版)

在这里插入图片描述

一:单向1-1关联

以老夫老妻为例子来说明一下,在中国以前是以丈夫主导地位,所以我这里以t_husband作为主表,t_wife作为从表

1.1:无连接表的单向1-1

(1)首先创建实体类,然后使用注解表示出来两者的关联关系

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "t_husband")
public class Husband {
	
	@Id @Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer hid;
	private String hname;
	
	public Husband() {
		super();
	}
	
	public Husband(String hname) {
		this.hname = hname;
	}

	public Integer getHid() {
		return hid;
	}
	public void setHid(Integer hid) {
		this.hid = hid;
	}
	public String getHname() {
		return hname;
	}
	public void setHname(String hname) {
		this.hname = hname;
	}
	
}
@Entity
@Table(name = "t_wife")
public class Wife {

	@Id @Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer wid;
	private String wname;
	@OneToOne(targetEntity = Husband.class,cascade = CascadeType.ALL)
	@JoinColumn(name = "hid",referencedColumnName = "hid")
	private Husband husband;
	
	public Wife() {
		super();
	}
	
	public Integer getWid() {
		return wid;
	}
	public void setWid(Integer wid) {
		this.wid = wid;
	}
	public String getWname() {
		return wname;
	}
	public void setWname(String wname) {
		this.wname = wname;
	}
	public Husband getHusband() {
		return husband;
	}
	public void setHusband(Husband husband) {
		this.husband = husband;
	}
	
}

(2)然后和xml配置的方式相同,使用mapping标签引入到hibernate的核心配置中去,只不过如果是xml配置的方式是resource属性,而注解的方式是class属性而已

		<!-- <mapping resource="cn/itcast/manyTomany/Teacher.hbm.xml"/> -->
		<mapping class="cn.itcast.entity.Husband"></mapping>
		<mapping class="cn.itcast.entity.Wife"></mapping>

(3)然后执行

	public class SingleAssociationDemo {
	private Transaction tx;
	private Session session;
	private SessionFactory sessionFactory;

	@Before
	public void before() {
		Configuration cfg = new Configuration().configure();
		sessionFactory = cfg.buildSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
	}
	
	@After
	public void after() {
		tx.commit();
		session.close();
		sessionFactory.close();
	}
	
	@Test
	public void testOneToOne() {
		//创建一个瞬时态的Husband对象
		Husband husband = new Husband("张三");
		
		//创建一个瞬时态的Wife对象
		Wife wife = new Wife();
		wife.setWname("西施");
		wife.setHusband(husband);
		
		session.save(wife);
	}
}

(4)最终数据库中生成的表的sql语句: 使用show create table 表名

	CREATE TABLE `t_husband` (
	  `hid` int(11) NOT NULL AUTO_INCREMENT,
	  `hname` varchar(255) DEFAULT NULL,
	  PRIMARY KEY (`hid`)
	) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
	CREATE TABLE `t_wife` (
	  `wid` int(11) NOT NULL AUTO_INCREMENT,
	  `wname` varchar(255) DEFAULT NULL,
	  `hid` int(11) DEFAULT NULL,
	  PRIMARY KEY (`wid`),
	  KEY `FK14fb3xipo2gwpwku60lkhqsqy` (`hid`),
	  CONSTRAINT `FK14fb3xipo2gwpwku60lkhqsqy` FOREIGN KEY (`hid`) REFERENCES `t_husband` (`hid`)
	) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

(5)表之间的结构图

在这里插入图片描述
(6)大概解释一下注解的含义
在这里插入图片描述

1.2:有连接表的单向1-1

注:非常少见,此处不再介绍!

二:单向1-N关联

以经典的部门和员工的关系来说明一下,一个部门有多个员工,所以在Deparement类中需要关联Employee类,因为是单向关系,所以在Employee类中不需要关联Department类,在hibernate中表示这种多的关系,推荐使用Set集合。

2.1:无连接表的单向1-N

(1)首先创建实体类,然后使用注解表示出来两者的关联关系

@Entity
@Table(name="t_department")
public class Department {

	@Id @Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer did;
	private String dname;
	@OneToMany(targetEntity = Employee.class, cascade = CascadeType.ALL)
	@JoinColumn(name="did", referencedColumnName = "did")
	private Set<Employee> employees = new HashSet<Employee>();
	//省了get/set方法
}
@Entity
@Table(name="t_employee")
public class Employee {

	@Id @Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer eid;
	private String ename;
	//省了get/set方法
}

(2)引入到核心配置文件:hibernate.cfg.xml

	<mapping class="cn.itcast.entity.Department"></mapping>
	<mapping class="cn.itcast.entity.Employee"></mapping>

(3)然后测试执行:是基于在SingleAssociationDemo 类中执行的

	@Test
	public void testOneToMany() {
		//创建瞬时态的Employee对象
		Employee employee1 = new Employee();
		employee1.setEname("wzj");
		Employee employee2 = new Employee();
		employee2.setEname("sbt");
		
		//创建瞬时态的Department对象
		Department department = new Department();
		department.setDname("技术部");
		department.getEmployees().add(employee1);
		department.getEmployees().add(employee2);
		
		session.save(department);
	}

(4)生成表的sql语句

	CREATE TABLE `t_department` (
	  `did` int(11) NOT NULL AUTO_INCREMENT,
	  `dname` varchar(255) DEFAULT NULL,
	  PRIMARY KEY (`did`)
	) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
CREATE TABLE `t_employee` (
	  `eid` int(11) NOT NULL AUTO_INCREMENT,
	  `ename` varchar(255) DEFAULT NULL,
	  `did` int(11) DEFAULT NULL,
	  PRIMARY KEY (`eid`),
	  KEY `FK32y5pu17i9yt51r6365lh0o2c` (`did`),
	  CONSTRAINT `FK32y5pu17i9yt51r6365lh0o2c` FOREIGN KEY (`did`) REFERENCES `t_department` (`did`)
	) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

(5)表之间的结构图
在这里插入图片描述
(6)大概解释下注解的含义
在这里插入图片描述

2.2:有连接表的单向1-N

有连接的1-N就说明会产生中间表(连接表)
还是以部门和员工为例子:
(1)首先创建实体类,然后使用注解表示出来两者的关联关系

	@Entity
@Table(name="t_department")
public class Department {

	@Id @Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer did;
	private String dname;
	@OneToMany(targetEntity = Employee.class)
	/**
	 * a.name为连接表的表名
	 * b.joinColumns中name="deptno", referencedColumnName = "did"
	 * 		表示当前实体Department,在连接表中的外键列名为deptno,引用当前实体的主键did
	 * c.inverseJoinColumns中name="empno", referencedColumnName="eid", unique=true
	   *             表示当前实体的关联实体,在连接表中的外键列名为empno, 引用关联实体的主键eid,unique=true就说明empno外键值唯一
	 */
	@JoinTable(name = "dept_emp_middle", 
			   joinColumns = @JoinColumn(name="deptno", referencedColumnName = "did"),
			   inverseJoinColumns = @JoinColumn(name="empno", referencedColumnName="eid", unique=true)
			)
	private Set<Employee> employees = new HashSet<Employee>();
	public Integer getDid() {
		return did;
	}
	public void setDid(Integer did) {
		this.did = did;
	}
	public String getDname() {
		return dname;
	}
	public void setDname(String dname) {
		this.dname = dname;
	}
	public Set<Employee> getEmployees() {
		return employees;
	}
	public void setEmployees(Set<Employee> employees) {
		this.employees = employees;
	}
}

因为是单向的,所以Employee还是与普通的实体类一样没有什么变化!
(2)引入到核心配置文件
(3)然后测试执行:是基于在SingleAssociationDemo 类中执行的

	@Test
	public void testOneToManyAndJoinTable() {
		//创建瞬时态的Employee对象
		Employee employee1 = new Employee();
		employee1.setEname("wzj");
		Employee employee2 = new Employee();
		employee2.setEname("sbt");
		
		//org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.itcast.entity.Employee
		//刚开始报错,看了一下报错信息,然后手动将Employee持久化,就好了,暂时不知道为啥
		session.persist(employee1);
		session.persist(employee2);
		
		//创建瞬时态的Department对象
		Department department = new Department();
		department.setDname("技术部");
		department.getEmployees().add(employee1);
		department.getEmployees().add(employee2);
		
		session.save(department);
		
	}

(4)生成表的sql语句

	CREATE TABLE `t_department` (
	  `did` int(11) NOT NULL AUTO_INCREMENT,
	  `dname` varchar(255) DEFAULT NULL,
	  PRIMARY KEY (`did`)
	) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
	CREATE TABLE `t_employee` (
	  `eid` int(11) NOT NULL AUTO_INCREMENT,
	  `ename` varchar(255) DEFAULT NULL,
	  PRIMARY KEY (`eid`)
	) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
CREATE TABLE `dept_emp_middle` (
	  `deptno` int(11) NOT NULL,
	  `empno` int(11) NOT NULL,
	  PRIMARY KEY (`deptno`,`empno`),
	  UNIQUE KEY `UK_1o2i9petja7s7tvwpc5ulqdh9` (`empno`),
	  CONSTRAINT `FK8te09d5x1sulwl9vkpec2b1qc` FOREIGN KEY (`deptno`) REFERENCES `t_department` (`did`),
	  CONSTRAINT `FKaudnndo58fbfmomdh4fal1cia` FOREIGN KEY (`empno`) REFERENCES `t_employee` (`eid`)
	) ENGINE=InnoDB DEFAULT CHARSET=utf8

(5)表之间的结构图
在这里插入图片描述
由于采用连接表的单向1-N关联,两个实体对应的数据表都无须增加外键列
因此不存在主从表关系,程序完全可以想先持久化哪个实体,就先持久化哪个实体,
无连接的一般是使用@JoinColumn:作为外键列
有连接的一般是使用@JoinTable:作为中间表

三:单向N-N关联

多对多没有有连接表,无连接表之说,多对多的关系,本来就需要第三张表
单向多对多和单向一对多很相似,就是不用inverseJoinColumns 中添加unique=true即可
(1)首先创建实体类

@Entity
@Table(name = "t_teacher")
public class Teacher {

	@Id @Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer tid;
	private String tname;
	@ManyToMany(targetEntity = Student.class)
	@JoinTable(name = "stu_teach_middle",
			   joinColumns = @JoinColumn(name="teacherId", referencedColumnName="tid"),
			   inverseJoinColumns = @JoinColumn(name="stuId", referencedColumnName="sid")
			)
	private Set<Student> students = new HashSet<Student>();
	//省了get/set
}
	@Entity
@Table(name = "t_student")
public class Student {
	
	@Id @Column
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer sid;
	private String sname;
	//省了get/set
}

(2)引入到核心配置文件
(3)然后测试执行:是基于在SingleAssociationDemo 类中执行的

	@Test
	public void testManyToManyAndJoinTable() {
		//创建瞬时态的Student对象
		Student s1 = new Student("张三");
		Student s2 = new Student("李四");
		
		//org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.itcast.entity.Employee
		//刚开始报错,看了一下报错信息,然后手动将Student持久化,就好了,暂时不知道为啥
		session.persist(s1);
		session.persist(s2);
		
		//创建瞬时态的Teacher对象
		Teacher t1 = new Teacher();
		t1.setTname("王老师");
		t1.getStudents().add(s1);
		t1.getStudents().add(s2);
		
		Teacher t2 = new Teacher();
		t2.setTname("崔老师");
		t2.getStudents().add(s1);
		t2.getStudents().add(s2);
		
		session.save(t1);
		session.save(t2);
	}

(4)生成表的sql语句

	CREATE TABLE `t_teacher` (
	  `tid` int(11) NOT NULL AUTO_INCREMENT,
	  `tname` varchar(255) DEFAULT NULL,
	  PRIMARY KEY (`tid`)
	) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
	CREATE TABLE `t_student` (
	  `sid` int(11) NOT NULL AUTO_INCREMENT,
	  `sname` varchar(255) DEFAULT NULL,
	  PRIMARY KEY (`sid`)
	) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
	CREATE TABLE `stu_teach_middle` (
	  `teacherId` int(11) NOT NULL,
	  `stuId` int(11) NOT NULL,
	  PRIMARY KEY (`teacherId`,`stuId`),
	  KEY `FKb25u37kv24u0o0e5hrm1q3g1w` (`stuId`),
	  CONSTRAINT `FKb25u37kv24u0o0e5hrm1q3g1w` FOREIGN KEY (`stuId`) REFERENCES `t_student` (`sid`),
	  CONSTRAINT `FKt4k47wtuu528b2hgm5tg35uhr` FOREIGN KEY (`teacherId`) REFERENCES `t_teacher` (`tid`)
	) ENGINE=InnoDB DEFAULT CHARSET=utf8

(5)表之间的结构图
在这里插入图片描述
来自:虽然帅,但是菜的cxy

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值