JDBC之DAO层封装思想超详解

Posted siaok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDBC之DAO层封装思想超详解相关的知识,希望对你有一定的参考价值。

mysql版本:8.0.26
可视化客户端:sql yog
编译软件:IntelliJ IDEA 2019.2.4 x64
运行环境:win10 家庭中文版
jdk版本:1.8.0_361


目录


一、DAO是什么?

众所周知,Java是面向对象语言,数据在Java中通常是以对象的形式存在。而在数据库中,它的每张数据表我们可以视作是Java中的一个个类,而表的每一行记录和相应的字段,便可视作是一个个的对象和对象的属性。相应地字段值,便是对象的属性值。反之,Java的对象也可看作是数据库中数据表的每一行记录,而Java对象的属性名和属性值,就是记录的字段名和相应的字段值。

当Java程序通过JDBC与数据库交互时,我们把涉及 访问数据库的代码封装起来,这些类称为DAO,英文全称为Data Access Object。它相当于是一个数据访问接口,夹在业务逻辑与数据库资源中间,这样使得代码结构更加清晰、易于维护和扩展。

如下图所示:


二、案例演示

案例:尝试连接数据库0225db,以DAO层的封装思想的形式进行编码,访问部门表与员工表,实现增删改查相应的功能

2.1 准备数据

①建立员工表t_employee


Create Table

CREATE TABLE `t_employee` (
  `eid` int NOT NULL AUTO_INCREMENT COMMENT '员工编号',
  `ename` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '员工姓名',
  `salary` double NOT NULL COMMENT '薪资',
  `commission_pct` decimal(3,2) DEFAULT NULL COMMENT '奖金比例',
  `birthday` date NOT NULL COMMENT '出生日期',
  `gender` enum('男','女') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '男' COMMENT '性别',
  `tel` char(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '手机号码',
  `email` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邮箱',
  `address` varchar(150) DEFAULT NULL COMMENT '地址',
  `work_place` set('北京','深圳','上海','武汉') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '北京' COMMENT '工作地点',
  `hiredate` date NOT NULL COMMENT '入职日期',
  `job_id` int DEFAULT NULL COMMENT '职位编号',
  `mid` int DEFAULT NULL COMMENT '领导编号',
  `did` int DEFAULT NULL COMMENT '部门编号',
  PRIMARY KEY (`eid`),
  KEY `job_id` (`job_id`),
  KEY `did` (`did`),
  KEY `mid` (`mid`),
  CONSTRAINT `t_employee_ibfk_1` FOREIGN KEY (`job_id`) REFERENCES `t_job` (`jid`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `t_employee_ibfk_2` FOREIGN KEY (`did`) REFERENCES `t_department` (`did`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `t_employee_ibfk_3` FOREIGN KEY (`mid`) REFERENCES `t_employee` (`eid`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `t_employee_chk_1` CHECK ((`salary` > 0)),
  CONSTRAINT `t_employee_chk_2` CHECK ((`hiredate` > `birthday`))
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

②建立部门表t_department

CREATE TABLE `t_department` (
  `did` int NOT NULL AUTO_INCREMENT COMMENT '部门编号',
  `dname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '员工名称',
  `description` varchar(200) DEFAULT NULL COMMENT '员工简介',
  PRIMARY KEY (`did`),
  UNIQUE KEY `dname` (`dname`)
) ENGINE=InnoDB AUTO_INCREMENT=1012 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

2.2 创建bean包

目的:

创建两个类用于封装从t_employee和t_department拿过来的每一行记录

代码演示如下:

①创建department类,用于封装从t_department拿过来的每一行记录,同时一个department类的对象可以写入t_department表里


public class department 
    private Integer did;
    private String dname;
    private String description;

    public department() 
    

    public department(int did) 
        this.did = did;
    

    public department(int did, String dname, String description) 
        this.did = did;
        this.dname = dname;
        this.description = description;
    

    public department(String dname, String description) 
        this.dname = dname;
        this.description = description;
    

    public int getDid() 
        return did;
    

    public void setDid(int did) 
        this.did = did;
    

    public String getDname() 
        return dname;
    

    public void setDname(String dname) 
        this.dname = dname;
    

    public String getDescription() 
        return description;
    

    public void setDescription(String description) 
        this.description = description;
    

    @Override
    public String toString() 
        return "department" +
                "did=" + did +
                ", dname='" + dname + '\\'' +
                ", description='" + description + '\\'' +
                '';
    


②创建employee类,用于封装从t_employee拿过来的每一行记录,同时一个employee类的对象可以写入t_employee表里

import java.math.BigDecimal;
import java.util.Date;

public class employee 
    private Integer eid;
    private String ename;
    private Double salary;
    private BigDecimal commissioPct;
    private Date birthday;
    private String gender;
    private String tel;
    private String email;
    private String address;
    private String workPlace="北京";
    private Date hiredate;
    private Integer jobId;
    private Integer mid;
    private Integer did;

    public employee() 
    


    public employee(Integer eid) 
        this.eid = eid;
    

    public employee(String ename, Double salary, BigDecimal commissioPct, Date birthday, String gender, String tel, String email, String address, String workPlace, Date hiredate, Integer jobId, Integer mid, Integer did) 
        this.ename = ename;
        this.salary = salary;
        this.commissioPct = commissioPct;
        this.birthday = birthday;
        this.gender = gender;
        this.tel = tel;
        this.email = email;
        this.address = address;
        this.workPlace = workPlace;
        this.hiredate = hiredate;
        this.jobId = jobId;
        this.mid = mid;
        this.did = did;
    

    public employee(Integer eid, String ename, Double salary, BigDecimal commissioPct, Date birthday, String gender, String tel, String email, String address, String workPlace, Date hiredate, Integer jobId, Integer mid, Integer did) 
        this.eid = eid;
        this.ename = ename;
        this.salary = salary;
        this.commissioPct = commissioPct;
        this.birthday = birthday;
        this.gender = gender;
        this.tel = tel;
        this.email = email;
        this.address = address;
        this.workPlace = workPlace;
        this.hiredate = hiredate;
        this.jobId = jobId;
        this.mid = mid;
        this.did = did;
    


    public Integer getEid() 
        return eid;
    

    public void setEid(Integer eid) 
        this.eid = eid;
    

    public String getEname() 
        return ename;
    

    public void setEname(String ename) 
        this.ename = ename;
    

    public Double getSalary() 
        return salary;
    

    public void setSalary(Double salary) 
        this.salary = salary;
    

    public BigDecimal getCommissioPct() 
        return commissioPct;
    

    public void setCommissioPct(BigDecimal commissioPct) 
        this.commissioPct = commissioPct;
    

    public Date getBirthday() 
        return birthday;
    

    public void setBirthday(Date birthday) 
        this.birthday = birthday;
    

    public String getGender() 
        return gender;
    

    public void setGender(String gender) 
        this.gender = gender;
    

    public String getTel() 
        return tel;
    

    public void setTel(String tel) 
        this.tel = tel;
    

    public String getEmail() 
        return email;
    

    public void setEmail(String email) 
        this.email = email;
    

    public String getAddress() 
        return address;
    

    public void setAddress(String address) 
        this.address = address;
    

    public String getWorkPlace() 
        return workPlace;
    

    public void setWorkPlace(String workPlace) 
        this.workPlace = workPlace;
    

    public Date getHiredate() 
        return hiredate;
    

    public void setHiredate(Date hiredate) 
        this.hiredate = hiredate;
    

    public Integer getJobId() 
        return jobId;
    

    public void setJobId(Integer jobId) 
        this.jobId = jobId;
    

    public Integer getMid() 
        return mid;
    

    public void setMid(Integer mid) 
        this.mid = mid;
    

    public Integer getDid() 
        return did;
    

    public void setDid(Integer did) 
        this.did = did;
    

    @Override
    public String toString() 
        return "employee" +
                "eid=" + eid +
                ", ename='" + ename + '\\'' +
                ", salary=" + salary +
                ", commission_pct=" + commissioPct +
                ", birthday=" + birthday +
                ", gender='" + gender + '\\'' +
                ", tel='" + tel + '\\'' +
                ", email='" + email + '\\'' +
                ", address='" + address + '\\'' +
                ", work_place='" + workPlace + '\\'' +
                ", hiredate=" + hiredate +
                ", job_id=" + jobId +
                ", mid=" + mid +
                ", did=" + did +
                '';
    


2.3 建立DAO包

2.2.1 建立BaseDAOImpl类

目的:

基本上每一个数据表都应该有一个对应的DAO接口及其实现类,发现对所有表的操作(增、删、改、查)代码重复度很高,所以可以抽取公共代码,给这些DAO的实现类可以抽取一个公共的父类,称为BaseDAOImpl。该类包含通用的增删改查的方法。

代码演示如下:

import util.JDBCTools;
import util.JDBCTools2;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public abstract class BaseDAOImpl 

    //通用的曾,删,改操作
    //sql中包含? 参数,需要设置?的值
    //如果sgL中没有?,那么调用这个方法时,不用传args对应的实参
    // 如果sgL中有5个?,那么调用这个方法时,要给args传入对应的5个实参
    //实现流程 : java程序  ---->  mysql数据库中的数据表
    public int update(String sql,Object ...args) throws SQLException 
        //连接数据库,类似于网络编程中的socket
        //使用JDBCTools(1.0)获取的连接对象
        Connection conn = JDBCTools.getConnection();

		//使用JDBCTools2(2.0)获取的连接对象
  //      Connection conn = JDBCTools2.getConnection();

        //将sql语句预编译
        PreparedStatement pst = conn.prepareStatement(sql);

        if (args!=null && args.length>0) 
            for (int i = 0; i < args.length; i++) 
               pst.setObject(i+1,args[i]);//设置?的值
            
        

        int len= pst.executeUpdate();//执行sql语句并返回同步更新的记录条数
        //释放连接
//        JDBCTools.freeConnection(conn);

        return len;
    



    //查询多个对象的信息的通用方法
    //实现流程:  Mysql数据库中的数据表的记录  --->  java程序中
    protected <T> List<T

Hibernate 学习笔记

Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,它将 POJO 与数据库表建立映射关系,是一个全自动的 orm 框架

hibernate(持久化)

一. Hibernate 的理解

Hibernate 是数据访问层(Dao层),就是把数据存入到数据库中,称为持久化。

Hibernate 对 JDBC 进行了封装,针对数据访问层提出面向对象的思想,操作对象间接的操作数据库中的表,自动生成 SQL 语句,可以简化数据访问层的代码,提高开发效率。

二. hibernate的优缺点

  • 优点:

    • 使用 JDBC 遇到的问题:

      1. 代码中存在大量的 SQL 语句

      2. 查询结果需要手动封装到 Model

      3. SQL 语句中存储大量的?,需要手动赋值

      4. SQL 语句根据不同的数据库,有不同的函数,如果更换数据库,需要大量更改 SQL 语句,针对数据库移植性差

    • 使用 Hibernate 可以解决以上问题:

      1. Hibernate 操作对象自动生成 SQL 语句

      2. 查询结果自动赋值给 Model 类

      3. 自动赋值

      4. Hibernate 使用的是 HQL 语句,根据不同的方言,生成不同数据库的 SQL 语句,到达跨数据库平台

        注:数据迁移是软性项目中的大事情,特别难做,做项目时对数据库的选型尤为重要

  • 缺点:

    1. SQL语句自动生成,人工无法控制,使得 SQL 语句执行效率慢
    2. Hibernate 执行效率低
    3. Hibernate 特别耗内存,有一系列缓存机制

三. 什么是ORM(☆)

ORM 是一种编程思想(开发模式),全称:Object Relation Mapper(对象关系映射)

是为了解决面向对象与面向关系型数据库不匹配现象,通过一个配置文件把面向对象与面向关系型数据库关联起来

  • 类 --- 表
  • 属性 --- 字段
  • 对象 --- 记录
优点:使得数据访问层更面向对象,不用考虑关系型数据库,只要会面向对象即可,开发程序变简单了(Hibernate、MyBatis、Spring、JDBC)

四、搭建 Hibernate 环境

  1. 导包:在hibernate-release-4.3.11.Final/lib/required下所有 Jar 文件与数据库驱动包复制到项目中
  2. 引入 Hibernate 主配置文件,Hibernate.cfg.xml文件复制到项目中的 src 目录
  3. 创建一个 Model 类实现 Serializable 接口,对应一个表,并且在映射文件xxx.hbm.xml中配置
  4. 编写 Hibernate API 进行测试

五. Hibernate 的体系结构(Hibernate由哪几部分组成)(☆)

结构 描述
hibernate.cfg.xml 是 Hibernate 的主配置文件,用来配置数据库连接信息与 Hibernate 相关参数
XXX.hbm.xml 类与表之间的映射文件,一个类对应一个表,一个属性对应一个字段
实体类 用于封装数据库的表,一定要实现 Serializable 接口
Hibernate API 用于读取并解析配置文件,然后根据映射关系生成 SQL 语句,间接操作数据库

六. Hibernate 工作原理(☆)

  1. Configuration 类读取并解析配置文件(主配置文件、映射文件)
  2. 创建 SessionFactory(一个 SessionFactory 对应一个数据库)
  3. 打开 Session(Session 代表程序与数据库之间的一次会话,用来做表的增删改查)
  4. 创建事务(Transaction 代表数据库事务)
  5. 持久化操作(增删改查)
  6. 提交事务
  7. 关闭 Session
  8. 当应用程序停止,关闭 SessionFactory

注:SessionFactory 是一个重量级对象,创建销毁特别耗资源,应用程序创建一次,关闭一次

七. Hibernate 代码工作原理

  1. 获取 Configuration 类的对象(cfg)

  2. 调用 cfg.configure() 方法默认读取 src 根目录下的 hibernate.cfg.xml

  3. 调用cfg.buildSessionFactory()方法创建 Session 工厂(sf)

  4. 调用sf.openSession()方法获取 Session

  5. 若为添加、删除、修改操作,则开启事务

    Transaction ts = session.getTransaction()
    ts.begin();
    
  6. 进行持久化操作

    添加:e(obj);			
    删除:delete(obj);			
    修改:update(obj);			
    查询:get(类名.class, 1);	
    查询:load(类名.class, 1);
    添加和修改都支持:saveOrUpdate(obj);	
    
  7. 提交事务,关闭 Session,关闭 SessionFactory

    ts.commit();
    session.close();
    sf.close();
    

八. Hibernate 的映射类型

Hibernate 映射文件xxx.hbm.xml中,Java 数据类型与数据库数据类型相互转换,通过 type 属性进行指定,类型如下:
  1. 整数

    Java 类型 type 取值
    byte byte
    short short
    int Integer
    long long
  2. 小数

    Java 类型 type 取值
    float float
    double double
  3. 字符串

    Java 类型 type 取值
    String String
  4. 日期

    Java 类型 type 取值
    java.util.Date date
    java.sql.Date date
  5. 时间

    Java 类型 type 取值
    java.sql.Timestamp timestamp

注:建议手动创建表,不要让 Hibernate 生成表格,hibernate.hbm2ddl.auto配置成为 update

九. Hibernate 核心开发接口(常用的类与接口)(☆)

接口 描述
Configuration 读取并解析配置文件,然后创建 SessionFactory(是一个类)
SessionFactory 代表一个数据库,一个 SessionFactory 对应一个数据库,用于创建 Session(是一个接口)
Session 程序与数据库的一次会话,用于数据库表的增删改查(是一个接口)
Transaction 事务管理(是一个接口)
Query 与 Criteria 用于数据查询(是一个接口)

十. Hibernate 有多少种查询

  1. 主键查询:get()load()
  2. HQL 查询
  3. SQL 查询
  4. QBC 查询

查询效率由高到低排列:主键查询 > SQL 查询 > HQL 查询 > QBC 查询

十一. 查询方法延迟加载(☆)

  1. 什么是延迟加载?

    Hibernate 中存在一些方法,在查询的时候并没有马上发送 SQL 语句去数据库查询,而是返回一个空值对象,空值对象不是 null,而是新 new 出来的对象,除主键以外其他属性值为空,当程序真正使用到此对象时,才会发送 SQL 语句去数据库中查询,并且将结果赋值给此对象,这种查询称为延迟加载

  2. 为什么要用延迟加载?

    1. 在延迟的这段时间内,并没有访问数据库,可以节约内存开销,减少数据库的访问,提高使用效率
    2. 可以防止查询对象,但并没有真正的使用,这种情况下可以节约内存,减少数据库访问
  3. 如何使用延迟加载?

    1. Hibernate 中一些方法自带延迟加载机制,只要调用这些方法,就可以使用延迟加载

    2. 具有延迟加载机制的访问如下

      延迟加载 立即加载
      session.load() session.get()
      query.iterate() query.list()
  4. get() 与 load() 区别(☆)

    get():立即加载,立即发送 SQL 语句查询,如果没有查询到结果返回 null

    load():延迟加载,不会立即发送 SQL 语句查询,返回一个空值对象,真正使用到此对象,才会发送 SQL 语句。如果没有查询到结果,会抛出ObjectNotFoundException异常

  5. list() 与 iterate() 区别

    list():立即加载,立即发送 SQL 语句查询,返回一个对象集合,如果没有查询到数据,返回空集合

    iterate():延迟加载,首先会发送一条 SQL 语句把表中所有主键查询出来,在遍历的时候,根据主键发送 SQL 语句单个查询,有多少条记录就会发送多少条 SQL 语句查询

    注:建议使用立即加载

十二. 一级缓存(☆)

  1. 什么是一级缓存?

    Hibernate 在创建 Session 的时候,会给每个 Session 另外分配一片内存空间,用于缓存 Session 操作过的对象,这块儿内存称为一级缓存,一级缓存是

    Session 管理并且使用的,所以也称为:Session 缓存。

    一级缓存的生命周期与 Session 一致,Session 被创建时,一级缓存空间被分配,session.close()时,一级缓存被回收

  2. 一级缓存的作用?

    一级缓存用来缓存 Session 操作过的对象,相同数据不用每次都去查询数据库,直接从一级缓存中获取,提高查询效率

  3. 一级缓存的步骤?

    Session 优先查询一级缓存,首先去一级缓存中查询,查询不到才会发送 SQL 语句查询数据库,查询到结果之后会在一级缓存中存放一份,再次查询时,无需发送 SQL 语句查询数据库,直接从一级缓存中获取(在 Hibernate 中一级缓存优先于数据库,一级缓存与数据库数据不同步时,以一级缓存为主)

  4. 如何使用一级缓存?

    1. 一级缓存是默认开启,自动使用

    2. 一级缓存的特征:

      • 一级缓存是 Session 独享的,Session 与 Session 之间不能共享数据
      • Session 查询一组数据时,会将一组数据拆开存入一级缓存中,一级缓存中存储的是单个对象
      • 执行增删改时会同步一级缓存,当delete(Object obj)时,在一级缓存中会标记此对象可能被删除,再次查询时不会发送 SQL 语句查询,返回一个null 对象
    3. 管理缓存

      • clear():清空一级缓存
      • evict():清空一级缓存单个对象
      • flush():手动同步一级缓存与数据库,数据不一样,以一级缓存为主

十三. 二级缓存

SessionFactory 级别的缓存(需要配置)

Hibernate 二级缓存需要配置,在同一 SessionFactory 范围内,查询同一个对象多次,只会发送一条 SQL 语句(只会去数据库中查询一次),后面每次查询都是从二级缓存中去取数据

配置信息:
  1. 导入二级缓存的 Jar 包 ehcache oscache
  2. 把对应配置文件放入到 src 根目录下
  3. Hibernate.cfg.xml中开启二级缓存
  4. 声明哪些对象需要放入到二级缓存中

十四. 对象的持久性

什么是对象的持久性?

​ Hibernate 操作对象时,可以把对象看成三种状态::瞬时态,持久台,游离态/托管态

三种状态的规则?
  1. 瞬时态(transient)

    • 定义:对象刚刚被 new 出来,称为瞬时态
    • 规则:瞬时态可以被垃圾回收机制回收,一级缓存中没有,数据库中没有
  2. 持久态(persistent)

    • 定义:一级缓存中有,数据库中有,称为持久态
    • 规则:通过 save(),update(),saveOrUpdate(),get(),load(),HQL,SQL,QBC 方式操作过的对象,称为持久态对象
  3. 游离态(detached)

    • 定义:一级缓存中没有,数据库中有,称为游离态
    • 规则:通过 clear,evict,close 方式操作过的对象, 称为游离态对象

十五. 主键的生成策略

在映射文件(xxx.hbm.xml)中需要配置主键字段,并且需要配置主键的生成策略,通过 generator 标签指定
主键生成策略:
  1. sequence

    代码如下:

    <generator class="sequence">
    	<!-- 指定序列的名称 -->
    	<param name="sequence">t_person_seq</param>
    </generator>
    

    对应数据库:Oracle,DB2

  2. identity

    代码如下:

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

    对应数据库:MySQL,SQL Server

  3. native

    代码如下:
    <generator class="native"></generator>

    含义:native 是让 hibernate 自动选择一种主键方式,根据配置文件中的方言,从 sequence 与 identity 中选一个,方言配置的是 Oracle ,自动选择sequence,方言配置的是MySQL,自动选择 identity

  4. assigned

    代码如下:

    <generator class="assigned"></generator>

    含义:程序员手动分配主键,Hibernate 不会自动生成

  5. uuid

    代码如下:

    <generator class="uuid"></generator>

    含义:采用 UUID 算法生成一个32位十六进制的字符串作为主键

  6. increment

    代码如下:

    <generator class="increment"></generator>

    含义:查询表中最大 id 值, 把最大 id + 1 生成主键

    优点:适用与任何数据库

    缺点:并发量大时,会产生相同的 id,线程不安全,不推荐使用

十六. 关系映射

什么是关系映射?

​ 如果两张表之间有关系,Hibernate 允许我们将关系提取出来,并且映射的配置文件中,在对一个表的增删改查操作,Hibernate 通过这个映射关系,间接的操作另一张表的增删改查,这两个表的关系配置称为关系映射

关系映射类型?
  1. 多对一
  2. 一对多
  3. 一对一
  4. 多对多

十七. 多对一(重点)与一对多

  1. 设计

    两张表之间的关系为多对一或一对多,会在多的一端增加一个字段指向一的那端的主键

  2. 案例

    学生与班级:多个学生属于一个班级,一个班级有多个学生

    一对多添加会产生 N+1 条,尽量少用一对多,用多对一代替

    一对多配置:
    <!--
    set标签:指定是 set 集合
    name属性:类中的属性名
    -->
    <set name="students">
    
    <!--
    key标签:指定两个表之间关联字段(外键字段名称)
    column属性:外键字段的字段名
    -->
    <key column="f_classId"></key>
    
    <!--
    one-to-many标签:表示与哪个类发生了一对多的关系
    class属性:多对那端类的名称
    -->
    <one-to-many class="Student" />
    </set>
    
    多对一配置:
    <!--
    many-to-one 标签:多对一关系
    name 属性:类中属性的名称
    column 属性:表中的字段名(外键字段名)
    class 属性:外键属性的类(完整路径)
    -->
    <many-to-one name="cla" column="f_classId" class="com.zt.model.Classes"></many-to-one>
    

十八. 关联操作

关联查询(查询)
  • 延迟加载(对于关联属性,Hibernate 默认采用的是延迟加载,查询一端数据,不会关联出另一端数据)

    lazy="proxy/true" 	默认方式,采用懒加载
    lazy="false"		立即加载,关联的表数据会同时查询出来
    
  • 连接查询

    fetch="select"	默认方式,使用多条 SQL 语句查询
    fetch="join"	使用连接查询,一条 SQL 语句完成查询,使用此属性懒加载失效
    
  • join 查询

    String hql = "from Student s left join fetch s.cla";  左外连接
    String hql = "from Student s inner join fetch s.cla";  内连接
    
级联操作(增删改)
  • 什么是级联操作?

    在对一张表做增删改操作时,关联的另一张表也做增删改操作,称为级联操作

  • 如何设置级联操作?

    在映射文件中,关联映射配置 cascade 属性,用这个属性定义级联操作

  • cascade取值如下:

取值方式 描述
none 默认方式,不支持级联
all 支持增删改
save-update 支持增,改
delete 支持删

十九. 一对一(了解)

一对一的类型:

​ 主键一对一:包装两个标段主键相同

​ 外键一对一:在任意一端增加一个字段(外键字段)指向另一端的主键,并且这个字段有唯一约束(不能重复)

案例:

​ 学生与档案一对一,在学生表中增加一个字段指向档案表的主键,外键保证唯一性

二十. 多对多

什么是多对多?

​ 如果两张表的关系是多对多,必然产生一张中间表,中间表只有两个字段,分别为两张表的外键字段,这两个外键字段组合成复合主键

案例:

​ 一个班级由多个老师教学,一个老师可以教多个班级

多对多配置:
<!-- 
set标签:指定是 set 集合
name属性:类中的属性名
table:中间表的表名
-->
<set name="teachers" table="t_cla_tea">

<!--
column属性:当前表的主键的对应中间表的外键字段
-->
<key column="f_classId"></key>

<!--
many-to-many标签:多对多的关系映射
class属性:当前 set 集合元素对应的类名
column属性:对方表的主键对应中间表的外键字段名
-->
<many-to-many class="Teacher" column="f_teacherId"/>
</set>

二十一. Hibernate 查询语句

  1. 主键查询:load,get
  2. HQL 查询(Hibernate Query Language) :标准的SQL + 面向对象语言
  3. QBC 查询(Query By Criteria):完全的面向对象
  4. SQL 查询(Structured Query Language):结构化查询语言

以上是关于JDBC之DAO层封装思想超详解的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate01 概述

Hibernate01 概述

2018.10.7 理解Hibernate的工作原理及其中的ORM详解

hibernate-笔记

Spring之DAO一

jdbc封装模拟用户登录