Java操作数据库方式三Hibernate的使用之多表操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fightingXia/article/details/80952070

##概述

在开发中经常会遇到多表操作,Hibernate支持多表关联的操作。

数据库表的关联关系分为三种:

  1. 一对一,
  2. 一对多,
  3. 多对多,

下面以“一对多”的栗子讲述Hibernate对多表的操作。

##准备工作

该博客继承上个博客,继续使用student表,再创建一个score表,student表与score是“一对多”的关系,即一个学生可以有多个分数。

创建score表的sql语句如下:

create table score(
       id int primary key auto_increment,
       student_id int,    
       score int,
       type varchar(20),
       foreign key(student_id) references student(id)
);

注:必须指定score表的student_id字段是student表的外键。

##开发环境

Java操作数据库方式三Hibernate的使用之多表操作

##正式开发

一,创建Model类

student的Model类如下:

public class Student {
    private int id;
    private String name;
    private int age;

    private Set<Score> score = new HashSet<>();//此处使用集合,一个Student对应多个Score
  
//set和get方法略
}

score的Model类如下:

 public class Score{ 
    private int id;
    private int score;
    private String type;

    private Student student;
//set和get方法略
}

二,创建对象与表结构映射关系文件

对student.hbm.xml进行修改,修改之后的文件内容是:

<?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>
    <!--
        class用来描述一个类
           name 类的全名
           table 该持久化类对应的表名   可以不写,默认值为类名
           lazy 此时设置为false,表示不使用懒加载
     -->
    <class name="com.honor.sql.Student" table="student" lazy="false">
        <!--
              Student类字段与表结构字段对应关系
              name 属性的名称
              column 属性的名称对应的表的字段   可以不写  默认值就是属性的名称
              length  属性的名称对应的表的字段的长度  如果不写,默认是最大的长度
         -->
        <id name="id" column="id" length="5">
            <!-- 主键的产生器 -->
            <generator class="increment"></generator>
        </id>
        <property name="name" column="name" length="20" ></property>
 
        <property name="age" column="age" length="50" ></property>
        <set name="score"  fetch="join" >
            <key column="student_id"></key>
            <one-to-many class="com.honor.sql.Score"/>//
        </set>
    </class>
</hibernate-mapping>

创建score对应的映射文件score.hbm.xml,文件内容如下:

<?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>
    <!--
        class用来描述一个类
           name 类的全名
           table 该持久化类对应的表名   可以不写,默认值为类名
           lazy 此时设置为false,表示不使用懒加载
     -->
    <class name="com.honor.sql.Score" table="score" lazy="false">
        <!--
              Student类字段与表结构字段对应关系
              name 属性的名称
              column 属性的名称对应的表的字段   可以不写  默认值就是属性的名称
              length  属性的名称对应的表的字段的长度  如果不写,默认是最大的长度
         -->
        <id name="id" column="id" length="5">
            <!-- 主键的产生器 -->
            <generator class="increment"></generator>
        </id>
        <property name="score" column="score" length="50" ></property>
        <property name="type" column="type" length="50" ></property>
        <many-to-one name="student" class="com.honor.sql.Student" column="student_id"/>
    </class>
</hibernate-mapping>

三,创建hibernate框架的全局配置文件

hibernate.cfg.xml中添加score.hbm.xml的引用

        <!--加载model类与表结构映射关系文件-->
        <mapping resource="student.hbm.xml" />
        <mapping resource="score.hbm.xml" />

四,得到Session对象

 /**
     * 根据配置文件获取Session对象
     *
     * @return
     */
    public static Session getSession() {
        //加载hibernate全局配置文件
        Configuration cfg = new Configuration().configure("/hibernate.cfg.xml");
        SessionFactory factory = cfg.buildSessionFactory();
        //得到Session对象,所有的数据库操作都是通过Session对象来完成
        Session session = factory.openSession();
        return session;
    }

五,插入操作

public static boolean insertStudentAndScore() {
        //获取Session对象
        Session session = getSession();
        try {
            //开始事务
            session.beginTransaction();
            Student student = new Student();
            student.setName("zhaomin");
            student.setAge(18);

            Score score1 = new Score();
            score1.setType("yuwen");
            score1.setScore(123);

            Score score2 = new Score();
            score2.setType("yingyu");
            score2.setScore(150);

            student.getScore().add(score1);
            student.getScore().add(score2);

            score1.setStudent(student);
            score2.setStudent(student);

            session.save(student);//保存student对象

            session.save(score1);//保存score1
            session.save(score2);//保存score2
            //提交事务
            session.getTransaction().commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            //出现异常时回滚事务
            session.getTransaction().rollback();
        } finally {
            if (session != null) {
                if (session.isOpen()) {
                    session.close();//关闭session
                }
            }
        }
        return false;
    }

此时查看执行日志发现共执行了5次sql语句:


六,根据id查找单个对象

public static Student selectStudent(int id) {
        //获取Session对象
        Session session = getSession();
        try {
            session.beginTransaction();
            //根据id查询Student对象
            Student student = session.load(Student.class, id);
            session.getTransaction().commit();
            return student;
        } catch (Exception e) {
            e.printStackTrace();
            //出现异常时回滚事务
            session.getTransaction().rollback();
        } finally {
            if (session != null) {
                if (session.isOpen()) {
                    session.close();//关闭session
                }
            }
        }
        return null;
    }

注:此时代码与单表操作时相同,但结果不同,结果如下:


注:此时把student对应的core对象都查出来了。这是将lazy设置为false的坏处,如果一个学生关联了万条score将会非常占用内存。

七,根据其他条件得到对象集合

查询yingyu分数为150的学生:

public static List<Score> selectScoreList() {
        //获取Session对象
        Session session = getSession();
        try {
            session.beginTransaction();
            //定义hql语句,类似于sql语句,注意:此时Student是对象,并不是表名。在student.hbm.xml文件中指定Student类对应student表
            String hql = "from Score s where s.score = 150 and s.type = 'yingyu'";
            //String hql = " from Student s,Score c ";
            Query query = session.createQuery(hql);
            List scoreList = query.list();
            session.getTransaction().commit();
            return scoreList;
        } catch (Exception e) {
            e.printStackTrace();
            //出现异常时回滚事务
            session.getTransaction().rollback();
        } finally {
            if (session != null) {
                if (session.isOpen()) {
                    session.close();//关闭session
                }
            }
        }
        return null;
    }

结果如下:



##总结

使用Hibernate操作多表自由度很低,如果对多表查询较多建议使用MyBatis框架。





猜你喜欢

转载自blog.csdn.net/fightingXia/article/details/80952070