zoukankan      html  css  js  c++  java
  • hibernate的映射关系之一对多

    关系:事物之间相互作用、相互联系的状态。范围最大。

    联系:在关系数据库中表示实体与实体之间的联系,1:1,1:n,m:n。

    关联:表示对象之间的关系,既有数量性,又有方向性;动词:将对象之间通过某种方式联系起来。

    映射:这里指java对象和数据库表的一种对应关系。动词:形成这种对应关系。

    级联:有关系的双方中操作一方,另一方也将采取一些动作。

    关联的联系种类

    在不考虑关联的方向前提下,联系就是关系数据库中表示实体与实体之间的联系,1:1,1:n,m:n。

    一对一联系(1:1):如用户和身份证、一夫一妻

    一对多联系(1:n):如班级和学生

    多对多联系(m:n):如学生和选课

    关联的方向

    关联关系的方向可分为单向关联和双向关联。

    双向关联的方向其实就不重要了,因为通过任一一方都可以维护彼此的关系。也就是说:在双向关联中一对多和多对一都是一样的。

    利用Java Project项目演示试用Hibernate技术添加数据到数据库


    1 建立项目之后首先呢肯定是需要导入相关的JAR包的

    2 然后是创建实体类

    package cn.itcast.hiberate.sh.domain;
    
    public class Student {
        private Long sid;
        private String sname;
        private String description;
        public Long getSid() {
            return sid;
        }
        public void setSid(Long sid) {
            this.sid = sid;
        }
        public String getSname() {
            return sname;
        }
        public void setSname(String sname) {
            this.sname = sname;
        }
        public String getDescription() {
            return description;
        }
        public void setDescription(String description) {
            this.description = description;
        }
        @Override
        public String toString() {
            return "Student [sid=" + sid + ", sname=" + sname + ", description="
                    + description + "]";
        }
        
    }
    package cn.itcast.hiberate.sh.domain;
    
    import java.util.Set;
    
    public class Classes {
        private Long cid;
        private String cname;
        private String description;
        private Set<Student> students;
        public Long getCid() {
            return cid;
        }
        public void setCid(Long cid) {
            this.cid = cid;
        }
        public String getCname() {
            return cname;
        }
        public void setCname(String cname) {
            this.cname = cname;
        }
        public String getDescription() {
            return description;
        }
        public void setDescription(String description) {
            this.description = description;
        }
        public Set<Student> getStudents() {
            return students;
        }
        @Override
        public String toString() {
            return "Classes [cid=" + cid + ", cname=" + cname + ", description="
                    + description + ", students=" + students + "]";
        }
        public void setStudents(Set<Student> students) {
            this.students = students;
        }
        
    }

    Student映射文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <!-- name的值代表的是一个实体 -->
        <class name="cn.itcast.hiberate.sh.domain.Student">
            <!-- id用于指定主键  column,主键在数据库表列 ,  increment,主键自增 -->
            <!-- length,指定长度 type,类型,也可以不写 -->
            <id name="sid" length="5" type="java.lang.Long">
                <generator class="increment"></generator>
            </id>
            <!-- 表示表中普通的属性 -->
            <property name="sname" length="20" type="java.lang.String"></property>
            <property name="description" length="100" type="java.lang.String"></property>
        </class>
    </hibernate-mapping>

    Class映射文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <!-- name的值代表的是一个实体 -->
        <class name="cn.itcast.hiberate.sh.domain.Classes">
            <!-- id用于指定主键  column,主键在数据库表列 ,  increment,主键自增 -->
            <!-- length,指定长度 type,类型,也可以不写 -->
            <id name="cid" length="5" type="java.lang.Long">
                <generator class="increment"></generator>
            </id>
            <!-- 表示表中普通的属性 -->
            <property name="cname" length="20" type="java.lang.String"></property>
            <property name="description" length="100" type="java.lang.String"></property>
            <!-- set元素和实体类中的 private Set<Student> students; 相对应 -->
            <!-- 
                set元素对应类中的set集合
                通过set元素使classes表与student表建立关联
                   key是通过外键的形式让两张表建立关联
                   one-to-many是通过类的形式让两个类建立关联
                
                cascade 级联
                   save-update
                       1、当 保存班级的时候,对学生进行怎么样的操作
                            如果学生对象在数据库中没有对应的值,这个时候会执行save操作
                            如果学生对象在数据库中有对应的值,这个时候会执行update操作
                   delete
                   all
                inverse  维护关系
                   true      不维护关系     
                   false     维护关系
                   default   false
             -->
            <set name="students" cascade="save-update">
                <!-- 
                    key是用来描述外键
                 -->
                <key column="cid"></key>
                <one-to-many class="cn.itcast.hiberate.sh.domain.Student"/>
            </set>
        </class>
    </hibernate-mapping>

    3 然后是配置文件 hibernate.cfg.xml

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <!-- 
            一个session-factory只能连接一个数据库
        -->
    <session-factory>
        <!-- 
            数据库的用户名
        -->
        <property name="connection.username">root</property>
        <!-- 
            密码
        -->
        <property name="connection.password">root</property>
        <!-- 
            url
        -->
        <property name="connection.url">
            jdbc:mysql://localhost:3306/itcast_sh_hibernate
        </property>
        <!-- 
            作用:根据持久化类和映射文件生成表
            validate
            create-drop
            create
            update
        -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 
            显示hibernate内部生成的sql语句
        -->
        <property name="show_sql">true</property>
        <mapping resource="cn/itcast/hiberate/sh/domain/Classes.hbm.xml" />
        <mapping resource="cn/itcast/hiberate/sh/domain/Student.hbm.xml" />
    
    </session-factory>
    </hibernate-configuration>

    4 hibernate创建 sessionfactory 的工具类

    package cn.itcast.hibernate.sh.utils;
    
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.junit.Before;
    
    public class HibernateUtils {
        public static SessionFactory sessionFactory;
        public static String url;
        // 需要在加载的时候就进行配置
        @Before
        public void init(){
            // 创建 Configuration 对象
            Configuration configuration = new Configuration();
            // 加载配置文件
            configuration.configure(url);
            sessionFactory = configuration.buildSessionFactory();
        }
    }

    5 测试类   需要注意的是,hibernate 可以创建相对应的表,但是 数据库需要自己先创建好

    package cn.itcast.hibernate.sh.test;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test;
    
    import cn.itcast.hiberate.sh.domain.Classes;
    import cn.itcast.hiberate.sh.domain.Student;
    import cn.itcast.hibernate.sh.utils.HibernateUtils;
    
    public class TestOneToMany extends HibernateUtils{
        static{
            url="/hibernate.cfg.xml";
        }
        // 建表
        @Test
        public void  testCreateTable(){
            
        }
        // 创建一个班级
        /**
         * Hibernate: select max(cid) from Classes
           Hibernate: insert into Classes (cname, description, cid) values (?, ?, ?)
         */
        @Test
        public void save_classes(){
            Session session = sessionFactory.openSession();
            // 除了查询之外的操作都需要使用事务
            Transaction transaction = session.beginTransaction();
            Classes classes = new Classes();
            classes.setCname("峡谷1");
            classes.setDescription("召唤师峡谷");
            session.save(classes);     // 将临时状态的对象转换成持久化状态
            transaction.commit();
            session.close();
        }
        // 创建一个学生
        /**
         * Hibernate: select max(sid) from Student
           Hibernate: insert into Student (sname, description, sid) values (?, ?, ?)
         */
        @Test
        public void save_student(){
            // session 的实质可以看为一个数据库连接
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Student student = new Student();
            student.setSname("黑铁");
            student.setDescription("菜");
            session.save(student);
            transaction.commit();
            session.close();
        }
        // 创建一个班级的时候同事创建一个学生,级联同时维护关系所以student表的外键也有值了
        /**
         *  Hibernate: select max(cid) from Classes
            Hibernate: select max(sid) from Student
            Hibernate: insert into Classes (cname, description, cid) values (?, ?, ?)
            Hibernate: insert into Student (sname, description, sid) values (?, ?, ?)
            Hibernate: update Student set cid=? where sid=?
         */
        @Test
        public void saveClasses_cacade_saveStudent(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Classes classes = new Classes();
            classes.setCname("峡谷2");
            classes.setDescription("召唤师峡谷2");
            Student student = new Student();
            student.setSname("白银呢");
            student.setDescription("还是菜");
            Set<Student> students = new HashSet<Student>();
            students.add(student);
            classes.setStudents(students);
            session.save(classes);
            transaction.commit();
            session.close();
        }
        // 存在一个班级,新建一个学生
        /**
         *  Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, 
         *  classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=?
            Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, 
            students0_.sid as sid1_0_, students0_.sname as sname1_0_, students0_.description as descript3_1_0_ from Student students0_ where students0_.cid=?
            Hibernate: select max(sid) from Student
            Hibernate: insert into Student (sname, description, sid) values (?, ?, ?)
            Hibernate: update Student set cid=? where sid=?
         */
        @Test
        public void test_classes_saveStudent(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Classes classes = (Classes) session.get(Classes.class, 4L);
            Student student = new Student();
            student.setSname("白白");
            student.setDescription("有点菜");
            // classes 是持久化状态 可以直接添加
            classes.getStudents().add(student);
            session.save(classes);
            transaction.commit();
            session.close();
        }
        // 存在一个学生,新建一个班级
        /**
         *  Hibernate: select student0_.sid as sid1_0_, student0_.sname as sname1_0_, 
         *  student0_.description as descript3_1_0_ from Student student0_ where student0_.sid=?
            Hibernate: select max(cid) from Classes
            Hibernate: insert into Classes (cname, description, cid) values (?, ?, ?)
            Hibernate: update Student set cid=? where sid=?
         */
        @Test
        public void test_student_saveClasses(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Student student = (Student) session.get(Student.class, 1L);
            Classes classes = new Classes();
            classes.setCname("峡谷3");
            classes.setDescription("召唤师峡谷3");
            Set<Student> students = new HashSet<Student>();
            students.add(student);
            classes.setStudents(students);
            // 临时状态的 classes 需要 save
            session.save(classes);
            transaction.commit();
            session.close();
        }
        // 存在一个 班级和学生 ,将其建立连接
        /**
         *  Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, 
         *  classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=?
            Hibernate: select student0_.sid as sid1_0_, student0_.sname as sname1_0_, 
            student0_.description as descript3_1_0_ from Student student0_ where student0_.sid=?
            Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, students0_.sid as sid1_0_,
             students0_.sname as sname1_0_, students0_.description as descript3_1_0_ 
             from Student students0_ where students0_.cid=?
            Hibernate: update Student set cid=? where sid=?
    
         */
        @Test
        public void updateClasses_cascade_updateStudent(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Classes classes = (Classes) session.get(Classes.class, 2L);
            Student student = (Student) session.get(Student.class, 5L);
            classes.getStudents().add(student);
            transaction.commit();
            session.close();
        }
        // 把一个学生从一个班级解除关系
        /**
         *  Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, 
         *  classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=?
            Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, 
            students0_.sid as sid1_0_, students0_.sname as sname1_0_, students0_.description
             as descript3_1_0_ from Student students0_ where students0_.cid=?
            Hibernate: update Student set cid=null where cid=? and sid=?
         */
        @Test
        public void test_release(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Classes classes = (Classes) session.get(Classes.class, 2L);
            Set<Student> students = classes.getStudents();
            for(Student s : students){
                if(s.getSid() == 5){
                    students.remove(s);
                }
            }
            // 解除了学生5的关系
            transaction.commit();
            session.close();
        }
        // 解除一个班级下面的一些学生的关系
        @Test
        public void test_releaseR(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Classes classes = (Classes) session.get(Classes.class, 2L);
            Set<Student> students = classes.getStudents();
            for(Student s : students){
                
                    students.remove(s);
                
            }
            // 解除了班级2下面的关系
            transaction.commit();
            session.close();
        }
        // 删除学生
        /**
         * Hibernate: select student0_.sid as sid1_0_, student0_.sname as sname1_0_, 
         * student0_.description as descript3_1_0_ from Student student0_ where student0_.sid=?
           Hibernate: delete from Student where sid=?
         */
        @Test
        public void testDelete(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Student student = (Student) session.get(Student.class, 5L);
            session.delete(student);
            transaction.commit();
            session.close();
        }
        // 删除班级
        /**
         *  Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=?
            Hibernate: update Student set cid=null where cid=?
            Hibernate: delete from Classes where cid=?
            删除班级的同时级联删除了 学生表中相应的外键
         */
        @Test
        public void test_deleteClasses(){
            Session session = sessionFactory.openSession();
            Transaction transaction = session.beginTransaction();
            Classes classes = (Classes) session.get(Classes.class, 5L);
            session.delete(classes);
            transaction.commit();
            session.close();
        }
    }

    用于记忆整理,欢迎各位大神来指点

  • 相关阅读:
    052-247(新增70题2018)
    052-246(新增70题2018)
    052-245(新增70题2018)
    Java项目软件测试基础1
    hibernate基础02:封装hibernateUtil,实现CRUD
    hibernate基础01:创建hibernate Demo实例
    eclipse快捷键
    Java插入MySQL数据库中文乱码,步骤详解
    LINUX切换普通用户提示:命令行提示:-BASH-4.1$ ,问题解决
    Mysql如何让百万数据快速分页,提高查询效率
  • 原文地址:https://www.cnblogs.com/hello001/p/6812364.html
Copyright © 2011-2022 走看看