• Hibernate多对多映射(双向关联)实例详解——真


    一个学生可以选多门课

    一门课程有多个学生上

    实现步骤:

    一、学生

    (1)数据库创建学生数据表students,包含id,name字段

    设置id字段为主键,类型:bigint,自增

    设置name字段,类型:nvarchar(50)

    (2)创建Student.java实体类,对应数据表

    package com.zit.entities;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.persistence.Column;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    public class Student {
    
    	
    	private long id;
    	
    	private String name;
    	
    	private Set<Course> courses = new HashSet<Course>();
    	
    	public Student(){
    		
    	}
    
    	public long getId() {
    		return id;
    	}
    
    	public void setId(long id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Set<Course> getCourses() {
    		return courses;
    	}
    
    	public void setCourses(Set<Course> courses) {
    		this.courses = courses;
    	}
    	
    	
    }
    

      

    (3)创建映射文件Student.hbm.xml,表明映射关系

    1、Student.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD//EN"
     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
    
    <hibernate-mapping>
       <class name="com.zit.entities.Student" table="students">
          <id name="id" column="id" type="long" >
             <generator class="native"/>
          </id>
          <property name="name" column="name" type="string"/>
          <!-- 添加中间表映射 --> 
          <set name="courses" table="students_courses" cascade="save-update" inverse="false">
          		<key column="student_id"></key>
          		<many-to-many class="com.zit.entities.Course" column="course_id"></many-to-many>
          </set>
       </class>
    </hibernate-mapping>
    
    1)<class>的name:实体类路径, table:数据表名字
    
    (2)id的<generator class="native"/>:主键生成策略,因为我在数据表已让主键id字段自增,这里设置native(别的百度一下即可)
    
    (3)id的column:对应数据表字段id,数据表为bigint类型,对应Java的long类
    
    (4)<set>标签:设置中间表
    
      table:中间表表名,
    
      cascade:什么情况下进行关联操作,这里设为save-update,所以save时会进行关联操作
    
      inverse:true/false,由false的一方维护,这里是多对多,双方维护,双方都为false
    
      <key column>:对应中间表的字段student_id,指定为students表的id的外键
    
      <many-to-many>:class:它指出与Student类进行关联的类,即Course; column:指定为courses表的主键id的外键


    Course.hbm.xml中与之相反即可,具体见下面具体配置

    二、课程

    (1)数据库创建课程数据表courses,包含id,name字段(与学生表相同即可)

    设置id字段为主键,类型:bigint,自增

    设置name字段,类型:nvarchar(50)

    (2)创建Course.java实体类,对应数据表

    package com.zit.entities;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Course {
    
    	private long id;
    	
    	private String name;
    	
    	private Set<Student> students = new HashSet<Student>();
    	
    	public Course(){
    		
    	}
    
    	public long getId() {
    		return id;
    	}
    
    	public void setId(long id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Set<Student> getStudents() {
    		return students;
    	}
    
    	public void setStudents(Set<Student> students) {
    		this.students = students;
    	}
    	
    	
    	
    }
    

      

    (3)创建映射文件Course.hbm.xml,表明映射关系

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD//EN"
     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
    
    <hibernate-mapping>
       <class name="com.zit.entities.Course" table="courses">
          <id name="id" column="id" type="long" >
             <generator class="native"/>
          </id>
          <property name="name" column="name" type="string"/>
          <!-- 添加中间表映射 --> 
          <set name="students" table="students_courses" cascade="save-update" inverse="false">
          		<key column="course_id"></key>
          		<many-to-many class="com.zit.entities.Student" column="student_id"></many-to-many>
          </set>
       </class>
    </hibernate-mapping>
    

      

    三、中间表

    由Hibernate自动生成中间表,不需自己创建

    它是根据Student.hbm.xml和Course.hbm.xml中的映射自动生成对应字段,

    student_id字段,是students表的主键id的外键

    course_id字段,是courses表的主键id的外键

    如下图所示:

    四、 测试代码:

    (运行后自动生成中间表)

    1、一个学生,选了两门课——“语文”、“化学”

    2、一门课程,有两个学生——“杨洋1”、“杨洋2”

    	@Resource(name = "sessionFactory")
    	private SessionFactory sessionFactory;
    	
    	@Override
    	@Transactional
    	public void insert() {
    		//getCurrentSession()比openSession()安全,注意web.xml中的配置,不然会报错
    		Session session = sessionFactory.getCurrentSession();
    		Transaction tran = session.beginTransaction();
    		
    //		1、王晓东1选了两门课
    		Student s1 = new Student();
    		s1.setName("王晓东1");
    		
    		Course c1 = new Course();
    		c1.setName("语文");
    		Course c2 = new Course();
    		c2.setName("化学");
    		 
    		s1.getCourses().add(c1);
    		s1.getCourses().add(c2);
    
    		session.save(s1);
    		
    //		2、英语课有两个学生
    //		Course c3 = new Course();
    //		c3.setName("英语");
    //		Student s2 = new Student();
    //		s2.setName("杨洋1");
    //		Student s3 = new Student();
    //		s3.setName("杨洋2");
    //		c3.getStudents().add(s2);
    //		c3.getStudents().add(s3);
    //		session.save(c3);
    		
    		tran.commit();
    		session.flush();//
    		session.close();
    	}
    
    
    

      注意commit后,要flush刷到数据库

    我的SessionFactory使用了SSH框架的注解配置 (根据自己的方式来获得Session即可)

    SSH框架搭建完整实例参考我的另一篇博客:  http://www.cnblogs.com/Donnnnnn/p/7481357.html

    实现效果:

    1、一个学生,选了两门课——“语文”、“化学”

    (1)控制台显示执行的sql语句

    Hibernate: insert into students (name) values (?)
    Hibernate: insert into courses (name) values (?)
    Hibernate: insert into courses (name) values (?)
    Hibernate: insert into students_courses (student_id, course_id) values (?, ?)
    Hibernate: insert into students_courses (student_id, course_id) values (?, ?)

    可以看到,往学生表、课程表和中间表都插入了数据

    (2)数据库

    students表:

    courses表:

    students_courses表:

    2、一门课程,有两个学生——“杨洋1”、“杨洋2”

    同上

    参考别人博客:

    https://www.cnblogs.com/whgk/p/6121593.html

  • 相关阅读:
    解决Oracle SQL Developer无法连接远程服务器的问题
    [备忘] Automatically reset Windows Update components
    在ASP.NET MVC的Action中直接接受客户端发送过来的HTML内容片段
    Rehosting the Workflow Designer
    解决Onedrive经常无法访问的问题
    最好的简明NodeJS学习材料
    最好的Python简明教程
    在Linux(ubuntu server)上面安装NodeJS的正确姿势
    在Windows中安装NodeJS的正确姿势
    在Windows环境中开始Docker的学习和体验
  • 原文地址:https://www.cnblogs.com/Donnnnnn/p/7838703.html
Copyright © 2020-2023  润新知