• (十一)Hibernate中的多表操作(1):单向一对多


      



    一、单向一对多()

    • 案例一(用XML文件配置): 一个班级有多个学生,班级可以查看所有学生的信息。
    • ClassBean.java
    package bean;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * ClassBean entity. @author MyEclipse Persistence Tools
     */
    
    public class ClassBean implements java.io.Serializable {
    
        // Fields
    
        private Integer classid;
        private String classname;
    
        private Set<StudentBean> stuSet=new HashSet<StudentBean>();
         
        
        // Constructors
    
        /** default constructor */
        public ClassBean() {
        }
    
        /** minimal constructor */
        public ClassBean(Integer classid) {
            this.classid = classid;
        }
    
        /** full constructor */
        public ClassBean(Integer classid, String classname) {
            this.classid = classid;
            this.classname = classname;
        }
    
        // Property accessors
    
        public Integer getClassid() {
            return this.classid;
        }
    
        public void setClassid(Integer classid) {
            this.classid = classid;
        }
    
        public String getClassname() {
            return this.classname;
        }
    
        public void setClassname(String classname) {
            this.classname = classname;
        }
    
        public Set<StudentBean> getStuSet() {
            return stuSet;
        }
    
        public void setStuSet(Set<StudentBean> stuSet) {
            this.stuSet = stuSet;
        }
    
    }

    StudentBean.java

    package bean;
    
    /**
     * StudentBean entity. @author MyEclipse Persistence Tools
     */
    
    public class StudentBean implements java.io.Serializable {
    
        // Fields
    
        private Integer stuid;
        private String stuname;
        private Integer classId;
    
        // Constructors
    
        /** default constructor */
        public StudentBean() {
        }
    
        /** minimal constructor */
        public StudentBean(Integer stuid) {
            this.stuid = stuid;
        }
    
        /** full constructor */
        public StudentBean(Integer stuid, String stuname, Integer classId) {
            this.stuid = stuid;
            this.stuname = stuname;
            this.classId = classId;
        }
    
        // Property accessors
    
        public Integer getStuid() {
            return this.stuid;
        }
    
        public void setStuid(Integer stuid) {
            this.stuid = stuid;
        }
    
        public String getStuname() {
            return this.stuname;
        }
    
        public void setStuname(String stuname) {
            this.stuname = stuname;
        }
    
        public Integer getClassId() {
            return this.classId;
        }
    
        public void setClassId(Integer classId) {
            this.classId = classId;
        }
    
    }
    • 单向一对多的映射文件 :

    ClassBean.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="bean.ClassBean" table="t_class" catalog="test">
            <id name="classid" type="java.lang.Integer">
                <column name="classid" />
                <generator class="assigned"></generator>
            </id>
            <property name="classname" type="java.lang.String">
                <column name="classname" />
            </property>
            
             <!--set元素,就是定义一个集合,它的name属性值是对应的POJO中的相关属性名称-->  
            <set name="stuSet" cascade="all">
                <key column="class_id"></key>  <!--指定“多”的一段的外键,与“一”端得主键相关联,这里的column=“class_id”是指数据库中的字段,而非bean中的属性,注意这里不会自动生成
                                                                    class_id属性,所以在bean.StudentBean类中要有一个外键的映射属性-->  
                <one-to-many class="bean.StudentBean"/>  <!--指定了“多”端对应的类-->
            </set>
        </class>
    </hibernate-mapping>
    • StudentBean.hbml.xml
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="bean.StudentBean" table="t_student" catalog="test">
            <id name="stuid" type="java.lang.Integer">
                <column name="stuid" />
                <generator class="assigned"></generator>
            </id>
            <property name="stuname" type="java.lang.String">
                <column name="stuname" />
            </property>
            <property name="classId" type="java.lang.Integer">
                <column name="class_id" />
            </property>
        </class>
    </hibernate-mapping>
    • 测试类
    package action;
    
    import java.util.Set;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import bean.ClassBean;
    import bean.StudentBean;
    import util.HibernateUtil;
    
    
    /**
     * 本类测试一对多的操作
     * @author 半颗柠檬、
     *
     */
    public class Test_ManytoOne {
        public static void main(String[] args) {
    //        Test_ManytoOne.save();
            
    //        Test_ManytoOne.select();
            
            Test_ManytoOne.delete();
        }
    
        public static void save(){
            Session session = null;
            Transaction tran = null;
            try {
                session = HibernateUtil.getSessionFactory().getCurrentSession();
                tran=session.beginTransaction();
                    
                
                ClassBean class1=new ClassBean();
                class1.setClassid(1);
                class1.setClassname("精英班");
                
                StudentBean stu1=new StudentBean();
                stu1.setClassId(class1.getClassid());
                stu1.setStuid(1);
                stu1.setStuname("学生1");
                
                StudentBean stu2=new StudentBean();
                stu2.setStuid(2);
                stu2.setStuname("学生2");
                stu2.setClassId(class1.getClassid());
                
                session.save(class1);
                session.save(stu1);
                session.save(stu2);
                
                tran.commit();
            } catch (Exception e) {
                e.printStackTrace();
                tran.rollback();
            }
        }
        
        /**
         * 测试“一”方能够读取“多”方的信息
         */
        private static void select() {
            Session session = null;
            Transaction tran = null;
            try {
                session = HibernateUtil.getSessionFactory().getCurrentSession();
                tran=session.beginTransaction();
                
                /**
                 * 由“一”方得知“多”方信息
                 */
                
               ClassBean cla=(ClassBean)session.get(ClassBean.class, new Integer(1));
              
               Set<StudentBean> stuSet=cla.getStuSet();
               
               for(StudentBean stu:stuSet){
                   
                   System.out.println(stu.getStuname());
                   System.out.println(stu.getClassId());
                   System.out.println(stu.getStuid());
               }
               
               
                
                
                tran.commit();
            } catch (Exception e) {
                e.printStackTrace();
                tran.rollback();
            }
        }
    
        /**
         * 删除One一方时,默认不会级联删除Many的一方。
         * 
         * 如果要级联删除:,一般使用代码手动级联更新
         * 
         * A:使用代码来控制级联删除。也是推荐使用的方式,手动进行级联删除,
         * 
         * B:配置级联关系,让Hibernate自动执行。
         * 
         * 在关联关系中配置cascade属性。
         * 
         * @OneToMany(cascade = { CascadeType.REMOVE, CascadeType.MERGE })
         * 
         */
        private static void delete() {
            Session session = null;
            Transaction tx = null;
            try {
                session = HibernateUtil.getSession();
                tx = session.beginTransaction();
        
                /**
                 * B  在关联关系中配置cascade属性之后
                 */
                ClassBean class1 = (ClassBean) session.get(ClassBean.class,
                        new Integer(1));
                session.delete(class1);
    
                tx.commit();
            } catch (Exception e) {
                e.printStackTrace();
                tx.rollback();
            } finally {
                HibernateUtil.closeSession();
            }
        }
        
        
    }


    案例二:使用注解测试单向一对多操作

    • 一个班级有多个学生,班级可以查看所有学生的信息,但是学生不能查看班级的信息。
    • ClassBean.java
    package bean;
    
    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "t_class")
    public class ClassBean implements Serializable {
        @Id
        private Integer classId;
    
        private String className;
    
        @OneToMany
        @JoinColumn(name = "class_id")   //不会在本类中自动创建名为classes_id的属性因为只有“多”方有外键,Hibernate会自动把本类中的所有属性都映射为数据库中的字段,所以该属性要
    //和表中的外键名一致,且Hibernate默认与StudentBean的主键相关联
    private Set<StudentBean> stuSet=new HashSet<StudentBean>(); public ClassBean() { } public ClassBean(Integer classId, String className) { super(); this.classId = classId; this.className = className; } public Integer getClassId() { return classId; } public void setClassId(Integer classId) { this.classId = classId; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public Set<StudentBean> getStuSet() { return stuSet; } public void setStuSet(Set<StudentBean> stuSet) { this.stuSet = stuSet; } }
    • StudentBean.java
    package bean;
    
    import java.io.Serializable;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "t_student")
    public class StudentBean implements Serializable {
    
        @Id
        @Column(name = "stuid")
        private Integer studentId;
    
        @Column(name = "stuname")
        private String studentName;
        
        @Column(name="class_id")
        private Integer classid;
    
        public StudentBean() {
    
        }
    
        public StudentBean(Integer studentId, String studentName) {
            super();
            this.studentId = studentId;
            this.studentName = studentName;
        }
    
        public Integer getStudentId() {
            return studentId;
        }
    
        public void setStudentId(Integer studentId) {
            this.studentId = studentId;
        }
    
        public String getStudentName() {
            return studentName;
        }
    
        public void setStudentName(String studentName) {
            this.studentName = studentName;
        }
    
        public Integer getClassid() {
            return classid;
        }
    
        public void setClassid(Integer classid) {
            this.classid = classid;
        }
    
    }
    • 设置总配置文件的映射关系
    <mapping class="bean.ClassBean" />
        <mapping class="bean.StudentBean" />
    • 测试一对多的操作
    package action;
    
    import java.util.List;
    import java.util.Set;
    
    import javax.persistence.CascadeType;
    import javax.persistence.OneToMany;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import bean.ClassBean;
    import bean.StudentBean;
    import util.HibernateUtil;
    
    /**
     * 本类测试一对多的操作
     * 
     * @author 半颗柠檬、
     * 
     */
    public class Test_ManytoOne {
        public static void main(String[] args) {
    //         Test_ManytoOne.save();
    
    //        Test_ManytoOne.select();
    
             Test_ManytoOne.delete();
        }
    
        public static void save() {
            Session session = null;
            Transaction tran = null;
            try {
                session = HibernateUtil.getSessionFactory().getCurrentSession();
                tran = session.beginTransaction();
    
                ClassBean class1 = new ClassBean();
                class1.setClassid(1);
                class1.setClassname("精英班");
    
                StudentBean stu1 = new StudentBean();
                stu1.setClassid(class1.getClassid());
                stu1.setStuid(1);
                stu1.setStuname("学生1");
    
                StudentBean stu2 = new StudentBean();
                stu2.setStuid(2);
                stu2.setStuname("学生2");
                stu2.setClassid(class1.getClassid());
    
                session.save(class1);
                session.save(stu1);
                session.save(stu2);
    
                tran.commit();
            } catch (Exception e) {
                e.printStackTrace();
                tran.rollback();
            }
        }
    
        /**
         * 测试“一”方能够读取“多”方的信息
         */
        private static void select() {
            Session session = null;
            Transaction tran = null;
            try {
                session = HibernateUtil.getSessionFactory().getCurrentSession();
                tran = session.beginTransaction();
    
                /**
                 * 由“一”方得知“多”方信息
                 */
    
                ClassBean cla = (ClassBean) session.get(ClassBean.class,
                        new Integer(1));
                Set<StudentBean> stuSet = cla.getStuSet();
    
                for (StudentBean stu : stuSet) {
    
                    System.out.println(stu.getStuname() + "	" + stu.getStuid()
                            + "	" + stu.getClassid());
    
                }
                // 过滤后的数据 ,这种方式会把排序注解忽略掉,即排序注解不会生效
                System.out.println("过滤后的数据.......");
                Query query = session.createFilter(stuSet,
                        "  where  stuid in (2,3)");
                List<StudentBean> stuList = query.list();
                for (StudentBean stu : stuList) {
    
                    System.out.println(stu.getStuname() + "	" + stu.getStuid()
                            + "	" + stu.getClassid());
    
                }
    
                /**
                 * 使用HQL语句。
                 */
    
                System.out.println("使用HQL语句");
                String hql = " select u from StudentBean u where stuid in(2,3) order by stuid desc ";
                query = session.createQuery(hql);
                stuList = query.list();
    
                for (StudentBean stu : stuList) {
    
                    System.out.println(stu.getStuname() + "	" + stu.getStuid()
                            + "	" + stu.getClassid());
    
                }
    
                tran.commit();
            } catch (Exception e) {
                e.printStackTrace();
                tran.rollback();
            }
        }
    
        /**
         * 删除one一方的时候,一般不删除多方,Hibernate会自动把多方的外键置空
         */
        private static void delete() {
            Session session = null;
            Transaction tx = null;
            try {
                session = HibernateUtil.getSession();
                tx = session.beginTransaction();
    
                /**
                 * B 在关联关系中配置cascade属性之后
                 */
                ClassBean class1 = (ClassBean) session.get(ClassBean.class,
                        new Integer(1));
                session.delete(class1);
    
                tx.commit();
            } catch (Exception e) {
                e.printStackTrace();
                tx.rollback();
            } finally {
                HibernateUtil.closeSession();
            }
        }
    
    }

    • 对于项目中大量使用@Entity注册在类头上,将一个类声明为一个实体bean(即一个持久化POJO类) , @Table注册在类头上,注解声明了该实体bean映射指定的表,来体现实体与表的这种映射关系。

      对于属性字段和表的字段关系对应的注解属性的位置,一般我们采用以下两种方式:

      第一种:

       是把注解@Column(name ="xx")放在field上,一种是把注解放在get方法上一般放在field上看起来比较集中、清晰;

      第二种:

       是把注解@Column(name= "xx")放在get方法上,这种方式看起来比较散漫、不很清楚;

      但是第一种方式这样做实际上破坏了Java面向对象的封装性,原因是一般我们写javaBean,成员变量通常定义为private,目的就是不让别人来直接访问的私有属性,而我们把注解放在私有成员的变量上,就是默认hibernate可以直接访问我们的私有的成员变量,所以我们定义属性为private,就实际没有多大意义,至于hibernate为什么能访问,hibernate采用java的反射机制完全可以访问私有成员变量!所以应该放在get方法上,第二种方式这个时候就显得更加合理。

    • 注意 :注意的一点,在一个实体类中,要么将映射注解全部放在成员变量上,要么全部放在成员方法上,不能各放一部分
  • 相关阅读:
    「CH2401」送礼物 解题报告
    IO流总结
    关于Servlet中GET和POST方法的总结
    关于Java-枚举的总结
    JVM原理
    Form表单中method="post/get'的区别
    基于Servlet+JSP+JavaBean开发模式的用户登录注册
    浅谈jsp和servlet的区别
    serialVersionUID作用
    oracle的oci和thin区别
  • 原文地址:https://www.cnblogs.com/shyroke/p/6853035.html
Copyright © 2020-2023  润新知