Hibernate

1.  内容

1.     Hibernate概述

2.     Hibernate入门

3.     Hibernate主键策略

4.     HQL入门

5.     Hibernate 关联关系

2.  Hibernate概述

 

2.1.   Hibernate是什么

Hibernate是一个基于ORM的持久层框架。

 

持久层框架:就是操作数据库的框架。(增删改查)

 

 

 

2.2.   ORM是什么

ORM (Object Relational Mapping),对象关系映射。就是在操作数据库之前,先将实体类与数据库表的关系建立起来。通过操作实体类的对象来操作数据库。这个就是ORM。

 

 

2.3.   ORM的作用是什么

ORM是一套实现基于对象操作数据库的理念。所以作用就是为了实现不用写SQL语句,通过对象操作数据库。

 

2.4.   Hibernate的作用是什么

既然Hibernate是一个基于ORM理念实现的持久层框架。那么它的作用就是,为了实现使用对象操作数据库。

 

2.5.   Hibernate的应用场景是什么

Hibernate实现了通过对象操作数据库。我们知道各种数据库的SQL语言和SQL标准是有差异的。Hibernate实现了各种主流数据库的方言,只有开发人员严格根据Hibernate规范编写代码。可以实现编写一套代码,兼容多种数据库。

 

所以在一些需要支持多种数据库的产品型项目,使用Hibernate可以减少持久层的代码的编写。

 

 

3.  Hibernate入门

3.1.   配置流程图

我们可以通过框架的配置流程图,快速了解框架的基础的必须要素。

 

 

 

问题:为什么需要一个配置文件?

答:因为我们需要一个配置文件,存储Hibernate框架的框架信息。如果没有配置文件只能将这些信息写在类里面。配置信息写在类里面,编译后就不能修改了。

 

问题:为什么需要一个映射文件?

答:因为Hibernate号称是一个ORM框架。需要先建立实体类与表的关系后,通过实体类的对象操作数据库。所以必须要有建立关系的映射文件,建立关系。

 

3.2.   配置步骤

根据以上配置流程图。我们可以得出配置步骤为:

1.     导入包(已知)

2.     创建一个配置文件

3.     创建一个获得操作对象(Session)的帮助类

4.     创建表的实体类

5.     创建映射关系文件

6.     加载映射文件

7.     实体操作(插入数据)

3.3.   Hibernate依赖jar说明

 

 

 

 

 

4.  入门示例

4.1.   需求

使用Hibernate框架,插入一条数据到学生表里面。

4.2.   准备:数据库脚本

CREATE TABLE `tb_student` (

`student_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '学生编号',

`student_name` VARCHAR(50) NOT NULL COMMENT '学生名',

`student_pwd` VARCHAR(50) NOT NULL COMMENT '密码',

`student_status` INT(11) NOT NULL COMMENT '学生状态',

`create_date` DATETIME NOT NULL COMMENT '创建日期',

PRIMARY KEY (`student_id`)

)

ENGINE=InnoDB

;

 

4.3.   配置步骤

4.3.1.   第一步:创建项目导入包

将Hibernate的zip压缩包的lib\required所有jar包加入到项目,以及mysql驱动包

 

 

 

4.3.2.   第二步:创建配置文件

注意事项:只要提供XML的框架,是必须提供DTD或者Schema规则文件的。我们需要在Eclipse配置XML的规则文件,让开发工具可以生产XML的头信息,以及对XML有提示。

Hibernate的规则文件DTD在Hibernate的核心包里面。

  

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "hibernate-configuration-3.0.dtd" >

<hibernate-configuration>

    <!-- 指定会话工厂的配置信息 -->

    <session-factory>

        <!-- 指定连接四要素

           理念:任何框架的设置的参数名,都可以在框架里面找到对应的代码!!!!!

           Environment:环境变量,Hibernate的参数声明都在这里。

         -->

        <property name="hibernate.connection.driver_class" >com.mysql.jdbc.Driver</property>

        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate-sms</property>

        <property name="hibernate.connection.username">root</property>

        <property name="hibernate.connection.password">123456</property>

       

        <!-- 指定显示SQL -->

        <property name="hibernate.show_sql">true</property>

        <property name="hibernate.format_sql">true</property>

       

        <!-- 指定加载的映射文件 -->

        <mapping resource="org/chu/pojo/hbm/Student.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

 

4.3.3.   第三步:创建HibernateUtils帮助类

package org.chu.utils;

 

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

 

public class HibernateUtils {

   

    public static final SessionFactory SESSION_FACTORY=HibernateUtils.getSessionFactory();

   

    //1.获得会话工厂

    private static SessionFactory getSessionFactory() {

        //1.创建配置对象

        Configuration configuration=new Configuration();

        //2.读取配置文件,默认路径为classpath:hibernate.cfg.xml

        Configuration configure = configuration.configure();

        //3.创建会话工厂

        SessionFactory factory = configure.buildSessionFactory();

        return factory;

       

    }

    //2.获得会话对象

    public static Session getSession() {

        return SESSION_FACTORY.openSession();

    }

   

    public static void main(String[] args) {

        System.out.println(HibernateUtils.getSession());

    }

 

}

 

 


4.3.4.   第四步:创建实体类
 

package org.chu.pojo;

 

import java.util.Date;

 

public class Student {

    private Integer studentId;//INT(11) NOT NULL AUTO_INCREMENT COMMENT '学生编号',

    private String studentName;//VARCHAR(50) NOT NULL COMMENT '学生名',

    private String studentPwd;//VARCHAR(50) NOT NULL COMMENT '密码',

    private Integer studentStatus;//INT(11) NOT NULL COMMENT '学生状态',

    private Date createDate;//DATETIME NOT NULL COMMENT '创建日期',

    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 String getStudentPwd() {

        return studentPwd;

    }

    public void setStudentPwd(String studentPwd) {

        this.studentPwd = studentPwd;

    }

    public Integer getStudentStatus() {

        return studentStatus;

    }

    public void setStudentStatus(Integer studentStatus) {

        this.studentStatus = studentStatus;

    }

    public Date getCreateDate() {

        return createDate;

    }

    public void setCreateDate(Date createDate) {

        this.createDate = createDate;

    }

}

 


4.3.5.   第五步:创建映射文件
 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "hibernate-mapping-3.0.dtd" >

<hibernate-mapping>

    <class name="org.chu.pojo.Student" table="tb_student">

        <!-- 指定主键对应关系

            问题:为什么ID字段需要单独分开?

            答:由于不同数据库的ID生成策略是有差异的,所以我们需要手工指定数据库的ID生成策略

         -->

        <id name="studentId" column="student_id">

          <!-- 数据库内置的自增长策略

            identity:使用内置的自增长策略

            native:使用数据库的内置策略

           -->

          <generator class="identity"></generator>

        </id>

        <!-- 指定普通属性的对应关系 -->

        <property name="studentName" column="student_name"></property>

        <property name="studentPwd" column="student_pwd"></property>

        <property name="studentStatus" column="student_status"></property>

        <property name="createDate" column="create_date"></property>

    </class>

</hibernate-mapping>

 


package
org.chu.test;4.3.6.   第六步:测试插入

import org.chu.pojo.Student;

import org.chu.utils.HibernateUtils;

import org.hibernate.Session;

import org.hibernate.Transaction;

import org.junit.Test;

 

public class StudentDAOTest {

   

    @Test

    public void save() {

        try {

            //第一步:获得操作对象

            Session session = HibernateUtils.getSession();

            //第二步:启动事务

            Transaction transaction = session.beginTransaction();

            Student student=new Student();

            student.setStudentName("张三");

            //第三步:插入

            session.save(student);

            //第四步:提交事务

            transaction.commit();

            //第五步:关闭

            session.close();

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

}

 


通过入门示例,我们果然实现了不要编写SQL语句,通过实体类对象就可以操作数据库了。 

 

5.  Hibernate主键策略

策略名

说明

 

increment

increment策略是指,不使用数据库本地的自增长策略,而是由程序(Hibernate框架)产生一个自增长的ID值,赋予数据库.

 
 

idenitty

identity策略,指定使用数据库里面的ID自增长策略. 只能用于有ID自增长功能的数据库,如:MySQL,SQLServer.. 不支持没有ID自增长策略的数据库,如Oracle,DB2..

 
 

sequence

使用序列的实现ID生成策略,主要用于有序列的数据库.如:Oracle,DB2,如果不支持序列的数据库(如:MYSQL),该策略会使用一个表模拟序列。

 
 

native

使用数据库本地的策略,就是数据库里面使用怎么样的策略就用什么策略,HIbernate不做任何的判断.如:MySQL数据库使用了increment_auto,自增长策略.使用native.表示直接调用数据库里面的increment_auto策略.

 

uuid

就是数据库的主键是使用一个唯一的字符串的来存储.这个唯一的字符串就是UUID

 
 

assigned

assigned策略,就是不使用主键生成策略,由手工输入ID.

 

 

 

 

 

6.  HQL入门

--使用入门示例的基础修改,StudentDAO类

6.1.   查询所有数据

 

 // 查询所有的数据,通过HQL

    @SuppressWarnings("unchecked")

    @Test

    public void findAll() {

        try {

            // 第一步:获得操作对象

            Session session = HibernateUtils.getSession();

 

            Query query = session.createQuery("from Student");

            List<Student> students = query.list();

            for (Student student : students) {

                System.out.println("学生名:" + student.getStudentName());

            }

 

            // 第五步:关闭

            session.close();

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

 


6.2.   统计记录
 

 // 查询所有的记录数

    @Test

    public void count() {

        try {

            // 第一步:获得操作对象

            Session session = HibernateUtils.getSession();

 

            Query query = session.createQuery("select count(*) from Student");

 

            Long count = (Long) query.uniqueResult();

 

            System.out.println(count);

            // 第五步:关闭

            session.close();

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

 


  

 

 

6.3.   模糊查询

 //需求:查询有张字的记录

    @Test

    public void findByCondition() {

       

        try {

            // 第一步:获得操作对象

            Session session = HibernateUtils.getSession();

 

            Query query = session.createQuery("from Student s where s.studentName like :sname");

            query.setParameter("sname", "%张%");

            List<Student> students = query.list();

            for (Student student : students) {

                System.out.println("学生名:" + student.getStudentName());

            }

 

            // 第五步:关闭

            session.close();

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

 


  

6.4.   条件删除

//通过条件删除,删除有李字的记录

    @Test

    public void deleteByName() {

        try {

            // 第一步:获得操作对象

            Session session = HibernateUtils.getSession();

 

            Query query = session.createQuery("delete from Student s where s.studentName like ? ");

            //从左到右,第一参数为0

            query.setParameter(0, "%李%");

            int executeUpdate = query.executeUpdate();

            System.out.println(executeUpdate);

            // 第五步:关闭

            session.close();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

 


7.  Hibernate 关联关系
 

7.1.   说明

Hibernate框架支持,通过配置映射关系,实现多表关联查询。

7.2.   准备SQL脚本

SET SESSION FOREIGN_KEY_CHECKS=0;

 

/* Drop Tables */

 

DROP TABLE IF EXISTS tb_result;

DROP TABLE IF EXISTS tb_student_identifer;

DROP TABLE IF EXISTS tb_student_teacher;

DROP TABLE IF EXISTS tb_student;

DROP TABLE IF EXISTS tb_teacher;

 

 

 

 

/* Create Tables */

 

-- 成绩表

CREATE TABLE tb_result

(

    result_id int NOT NULL AUTO_INCREMENT COMMENT '成绩编号',

    result_subject varchar(50) COMMENT '科目',

    result_score float COMMENT '分数',

    student_id int NOT NULL COMMENT '学生编号',

    PRIMARY KEY (result_id)

) COMMENT = '成绩表';

 

 

-- 学生表

CREATE TABLE tb_student

(

    student_id int NOT NULL AUTO_INCREMENT COMMENT '学生编号',

    student_name varchar(50) COMMENT '学生名',

    student_pwd varchar(50) COMMENT '密码',

    PRIMARY KEY (student_id)

) COMMENT = '学生表';

 

 

-- 学生身份信息表

CREATE TABLE tb_student_identifer

(

    student_id int NOT NULL COMMENT '学生编号',

    student_idcard varchar(30) COMMENT '身份证号码',

    student_number varchar(50) COMMENT '学号',

    PRIMARY KEY (student_id)

) COMMENT = '学生身份信息表';

 

 

-- 学生教师关系表

CREATE TABLE tb_student_teacher

(

    student_id int NOT NULL COMMENT '学生编号',

    teacher_id int NOT NULL COMMENT '教师编号'

) COMMENT = '学生教师关系表';

 

 

-- 教师表

CREATE TABLE tb_teacher

(

    teacher_id int NOT NULL AUTO_INCREMENT COMMENT '教师编号',

    teacher_name varchar(50) COMMENT '教师名字',

    teacher_pwd varchar(50) COMMENT '登录密码',

    PRIMARY KEY (teacher_id)

) COMMENT = '教师表';

 


7.3.   一对一的关系
 

7.3.1.   需求

配置一对一的关系。通过学生信息,查询学生的身份信息。

 

 

 

注意:我们通过入门示例修改代码。框架配置代码忽略了。

 

7.3.2.   配置步骤说明

配置表与表的关系,步骤就两步。

第一步:根据数据库设计,将表与表之间的关系建立在实体类里面。

第二步:在对应的映射文件,配置映射的关系。

 

7.3.3.   配置步骤

 

第一步:建立学生表与学生身份表的实体类的关系

package org.chu.pojo;

 

public class Student {

    private Integer studentId;// '学生编号',

    private String studentName;// '学生名',

    private String studentPwd;// '密码',

   

    //需求,通过Student查询StudentIdentifer表的记录,需要建立关系。

    //student与student_identifer是一对一的关系。所以使用引用

    private StudentIdentifer studentIdentifer;

 

   public StudentIdentifer getStudentIdentifer() {

       return studentIdentifer;

    }

    public void setStudentIdentifer(StudentIdentifer studentIdentifer) {

       this.studentIdentifer = studentIdentifer;

    }

 

   //补全get、set方法

}

 


第二步:配置映射文件的映射关系 

<hibernate-mapping>

    <class name="org.chu.pojo.Student" table="tb_student">

        <id name="studentId" column="student_id">

          <generator class="identity"></generator>

        </id>

        <!-- 指定普通属性的对应关系 -->

        <property name="studentName" column="student_name"></property>

        <property name="studentPwd" column="student_pwd"></property>

       

        <!-- 配置与StudentIdentifer的一对一的关系 -->

        <one-to-one name="studentIdentifer" foreign-key="student_id"></one-to-one>

       

    </class>

</hibernate-mapping>

 


第三步:测试代码

// 需求:通过ID查询学生表的信息,再查询学生的身份信息。

    @Test

    public void findById() {

        Session session = HibernateUtils.getSession();

        // 通过ID查询使用get方法。

        Student student = session.get(Student.class, 1);

        System.out.println("编号:" + student.getStudentId() + "学生名:" + student.getStudentName());

        // 注意:如何通过student对象查询到studentIdentifer表的记录,

        // (1)需要将表与表之间的关联关系建立在实体类里面。(2)并且配置好映射关系。

        StudentIdentifer identifer = student.getStudentIdentifer();

        System.out.println("学生身份证:" + identifer.getStudentIdcard());

        session.close();

    }

 

    @Test

    public void findAll() {

        Session session = HibernateUtils.getSession();

        // 通过ID查询使用get方法。

        Query query = session.createQuery("select s from Student s");

        List<Student> students = query.list();

        for (Student student : students) {

            System.out.println("编号:" + student.getStudentId() + "学生名:" + student.getStudentName());

            // 注意:如何通过student对象查询到studentIdentifer表的记录,

            // (1)需要将表与表之间的关联关系建立在实体类里面。(2)并且配置好映射关系。

            StudentIdentifer identifer = student.getStudentIdentifer();

            System.out.println("学生身份证:" + identifer.getStudentIdcard());

        }

 

        session.close();

    }

 

}

 


7.4.   一对多的关系
 

7.4.1.   需求

通过学生表的记录,查询学生的成绩记录。

 

 

 

 

7.4.2.   配置步骤

第一步:配置实体类的关联关系

在学生实体类Student加上以下代码

  //学生与成绩的关系是,一对多。所以使用集合,

    private Set<Result> results;

 

    public Set<Result> getResults() {

       return results;

    }

    public void setResults(Set<Result> results) {

       this.results = results;

    }

 


<!-- 配置学生与成绩的,一对多的关系 -->
第二步:配置学生映射关系文件

       <!-- set标签,用于配置Set集合的属性 -->

       <set name="results"  >

           <!-- 用于指定外键字段 -->

           <key column="student_id"></key>

           <!-- 用于指定一对多的关系,class:指定集合元素类性 -->

           <one-to-many class="org.chu.pojo.Result"  />

       </set>

 


7.5.   多对一配置
 

7.5.1.   需求

查询成绩的信息,在通过成绩信息查询学生信息。

 

7.5.2.   配置步骤

第一步:配置实体类的关系

在成绩实体类表(Result)表配置学生实体类的关系。

//配置成绩与学生的关系。多对一的关系。使用引用

    private Student student;

   

    public Student getStudent() {

       return student;

    }

 

    public void setStudent(Student student) {

       this.student = student;

    }

 


第二步:配置映射文件的关系 

<hibernate-mapping package="org.chu.pojo">

 

    <class name="Result" table="tb_result">

 

        <id name="resultId" column="result_id">

            <generator class="identity" />

        </id>

 

        <property name="resultSubject" column="result_subject"  />

        <property name="resultScore" column="result_score"  />

        <!-- <property name="studentId" column="student_id" insert="false" update="false"  />  -->

       

        <!-- 配置成绩与学生,多对一的关系

          name:配置多对一,引用的属性名,

          column:配置关联的外键字段

         -->

        <many-to-one name="student" column="student_id"></many-to-one>

    </class>

</hibernate-mapping>

 

 


 注意:要注释掉,原来外键字段的属性配置。

7.6.   多对多配置

需求:通过学生的记录查询学生的教师记录。

 

 

 

 

7.6.1.   配置步骤

第一步:配置实体类的关系

配置学生表与教师表的关系,在Student实体类加上以下代码

//配置学生与教师的关系,多对多。

    private Set<Teacher> teachers;

 

    public Set<Teacher> getTeachers() {

       return teachers;

    }

    public void setTeachers(Set<Teacher> teachers) {

       this.teachers = teachers;

    }

 


第二步:配置映射文件的关系 

 <!-- 配置学生与教师的多对多关系 -->

       <set name="teachers" table="tb_student_teacher">

         <!-- 指定本表在中间表的外键 -->

         <key column="student_id"></key>

         <!-- 指定多对多的关系

          class返回的集合,元素的类型

          column关联表在中间表的外键

          -->

         <many-to-many class="org.chu.pojo.Teacher" column="teacher_id"></many-to-many>

       </set>

 


第三步:测试代码 

// 需求:通过ID查询学生表的信息,再查询学生的教师信息。

    @Test

    public void findById() {

        Session session = HibernateUtils.getSession();

        // 通过ID查询使用get方法。

        Student student = session.get(Student.class, 1);

        System.out.println("编号:" + student.getStudentId() + "学生名:" + student.getStudentName());

        Set<Teacher> teachers = student.getTeachers();

        for (Teacher teacher : teachers) {

            System.out.println("教师名:"+teacher.getTeacherName());

        }

        session.close();

    }

 

 


 

posted @ 2020-09-04 17:58  小小穿梭机^^  阅读(664)  评论(0编辑  收藏  举报