三大框架 之 Hibernate查詢(一對多、多對多、查詢關係)

[TOC]java

一對多

表之間關係

​ 一對多sql

  • 一個部門有多個員工,一個員工只能屬於某一個部門
  • 一個班級有多個學生,一個學生只能屬於一個班級

​ 多對多數據庫

  • 一個老師教多個學生,一個學生能夠被多個老師教
  • 一個學生能夠先擇多門課程,一門課程能夠被多個學生選擇
  • 一個用戶能夠選擇多個角色,一個角色也能夠被多個用戶選擇

​ 一對一session

  • 一個公司只能對應一個註冊地址

表之間關係建表原則

​ 一對多 ​ 在多的一方建立一個外鍵,指向一的一方的主鍵 ​ 多對多 ​ 建立一箇中間表,中間表至少有兩個字段,分別做爲外鍵指向多對多雙方的主鍵 ​ 一對一 ​ 惟一外鍵對應 ​ 主鍵對應app

一對多關係配置

創建表

建立表的 hbm.xml文件時,有外鍵可不建立列的映射dom

主表爲客戶(Customer),從表爲聯繫人(Linkman)ide

銷售聯繫人(linkman),一個聯繫人只能屬於某一個客戶 ​工具

CREATE TABLE `linkman` (
  `link_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '聯繫人編號(主鍵)',
  `link_name` varchar(16) DEFAULT NULL COMMENT '聯繫人姓名',
  `link_cust_id` bigint(32) NOT NULL COMMENT '客戶id',
  `link_gender` char(1) DEFAULT NULL COMMENT '聯繫人性別',
  `link_phone` varchar(16) DEFAULT NULL COMMENT '聯繫人辦公電話',
  `link_mobile` varchar(16) DEFAULT NULL COMMENT '聯繫人手機',
  `link_email` varchar(64) DEFAULT NULL COMMENT '聯繫人郵箱',
  `link_qq` varchar(16) DEFAULT NULL COMMENT '聯繫人qq',
  `link_position` varchar(16) DEFAULT NULL COMMENT '聯繫人職位',
  `link_memo` varchar(512) DEFAULT NULL COMMENT '聯繫人備註',
  PRIMARY KEY (`link_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

客戶(customer),一個客戶能夠有多個聯繫人 ​測試

CREATE TABLE `customer` (
  `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)',
  `cust_name` varchar(32) NOT NULL COMMENT '客戶名稱(公司名稱)',
  `cust_source` varchar(32) DEFAULT NULL COMMENT '客戶信息來源',
  `cust_industry` varchar(32) DEFAULT NULL COMMENT '客戶所屬行業',
  `cust_level` varchar(32) DEFAULT NULL COMMENT '客戶級別',
  `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定電話',
  `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移動電話',
  PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

關係圖

創建ORM

實體類與數據庫中創建字段關係

Customer 實體類(一個客戶能夠有多個聯繫人)
package com.myxq.domain;
import lombok.Getter;
import lombok.Setter;
import java.util.HashSet;
import java.util.Set;
@Getter@Setter
public class Customer {
    private Long cust_id;
    private String cust_name;
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_phone;
    private String cust_mobile;
    //創建一個客戶能夠有多個聯繫人
    //放置多的一方的集合,hibernate默認使用的是Set集合
    //若是使用List的話,它要對List進行排列,在表中要多建這一列,用來排序
    //通常使用的都是Set集合
    //如今是雙向關聯,從客戶能查聯繫人,從聯繫人也能查客戶
    private Set<Linkman> linkmens = new HashSet<>();
    @Override
    public String toString() {
        return "Customer{" +
                "cust_id=" + cust_id +
                ", cust_name='" + cust_name + '\'' +
                ", cust_source='" + cust_source + '\'' +
                ", cust_industry='" + cust_industry + '\'' +
                ", cust_level='" + cust_level + '\'' +
                ", cust_phone='" + cust_phone + '\'' +
                ", cust_mobile='" + cust_mobile + '\'' +
                '}';
    }
}
Linkman 實體類(一個聯繫人只能屬於一個客戶)
package com.myxq.domain;
import lombok.Getter;
import lombok.Setter;
@Getter@Setter
public class Linkman {
    private Long   link_id;
    private String link_name;
    private String link_gender;
    private String link_phone;
    private String link_mobile;
    private String link_email;
    private String link_qq;
    private String link_position;
    private String link_memo;
    private String link_cust_id;
    //一個聯繫人只對應一個客戶
    private Customer customer;
    @Override
    public String toString() {
        return "Linkman{" +
                "link_id=" + link_id +
                ", link_name='" + link_name + '\'' +
                ", link_gender='" + link_gender + '\'' +
                ", link_phone='" + link_phone + '\'' +
                ", link_mobile='" + link_mobile + '\'' +
                ", link_email='" + link_email + '\'' +
                ", link_qq='" + link_qq + '\'' +
                ", link_position='" + link_position + '\'' +
                ", link_memo='" + link_memo + '\'' +
                ", link_cust_id='" + link_cust_id + '\'' +
                ", customer=" + customer +
                '}';
    }
}

添加配置文件

1.客戶(Customer)實體類的配置文件fetch

customer.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">
<hibernate-mapping>
    <class name="com.myxq.domain.Customer" table="customer" >
        <!--創建類屬性哪個是主鍵  還要跟數據庫當中主鍵進行對象-->
        <id name="cust_id" column="cust_id" >
            <generator class="native"/>
        </id>
        <!--創建類中的普通屬性與數據庫當中的表字段的映射,關聯-->
        <property name="cust_name" column="cust_name" />
        <property name="cust_source" column="cust_source"/>
        <property name="cust_industry" column="cust_industry"/>
        <property name="cust_level" column="cust_level"/>
        <property name="cust_phone" column="cust_phone"/>
        <property name="cust_mobile" column="cust_mobile"/>
        <!--一對多-->
        <set name="linkmens" cascade="save-update,delete" inverse="true"><!--set屬性名稱-->
            <key column="link_cust_id"></key><!--外鍵-->
            <one-to-many class="com.myxq.domain.Linkman"></one-to-many>
        </set>

    </class>
</hibernate-mapping>

2.聯繫人(LinkMan)實體類配置文件 linkman.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">
<hibernate-mapping>
    <class name="com.myxq.domain.Linkman" table="linkman" >
        <!--創建類屬性哪個是主鍵  還要跟數據庫當中主鍵進行對象-->
        <!-- 設置主鍵與OID的對應關係 -->
        <id name="link_id" column="link_id" >
            <generator class="native"/>
        </id>
        <!--創建類中的普通屬性與數據庫當中的表字段的映射  注意:外鍵不用設置-->
        <property name="link_name" column="link_name" />
        <property name="link_gender" column="link_gender"/>
        <property name="link_phone" column="link_phone"/>
        <property name="link_mobile" column="link_mobile"/>
        <property name="link_email" column="link_email"/>
        <property name="link_qq" column=" link_qq"/>
        <property name="link_position" column=" link_position"/>
        <property name="link_memo" column=" link_memo"/>

        <!--
                many-to-one:配置多對一
                name:一的一方對象屬性名稱
                class:一的一方類的全路徑
                column:多的一方表的外鍵名稱
        -->
        <many-to-one name="customer" cascade="save-update" class="com.myxq.domain.Customer" column="link_cust_id"/>
    </class>
</hibernate-mapping>

在hibernate.cfg.xml中的<session-factory>標籤裏,添加核心配置文件

<!--加載映射文件-->
		<mapping resource="com/myxq/domain/customer.hbm.xml" />
		<mapping resource="com/myxq/domain/linkman.hbm.xml" />
		<mapping resource="com/myxq/domain/role.hbm.xml" />
		<mapping resource="com/myxq/domain/user.hbm.xml" />

引入工具類

HibernateUtil.java

package com.myxq.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    public static final SessionFactory sessionFactory;
    static {
        //1.加載配置文件
        Configuration configure = new Configuration().configure();
        //configure.addResource("com/myxq/domain/Customer.hbm.xml");
        //2.建立sessionFactory   --JDBC 鏈接池
        sessionFactory = configure.buildSessionFactory();
    }
    public static Session openSession(){
        Session session = sessionFactory.openSession();
        return  session;
    }
    public static Session getCurrentSession(){
        Session session = sessionFactory.getCurrentSession();
        return  session;
    }
}

編寫測試類

級聯操做

問題 ​ 在兩張表創建一對多關係時,若是隻保存一邊的對象,就會發異常 示例

什麼是級聯

​ 在操做一個對象的時候,是否會操做其關聯的對象。

級聯分類

​ 級聯保存或更新 ​ 級聯刪除

級聯是有方向性

​ 在操做一的一方,是否會操做多的一方 ​ 操做多的一方時, 是否會操做一的一方

級聯保存或更新

級聯保存

​ 操做的主體是誰,就要在誰的映射配置文件當中進行配置 ​ 在開始配置的set當中添加一個新的屬性cascade="save-update"

​ 在多的一方添加級聯

​ 再去運行,就不會報異常,兩條記錄都會被添加 ​ 在一的一方添加級聯 ​

對象導航

​ 兩方若是都加了級聯,這種咱們也稱爲雙向導航 ​ 設置雙向導航時,當對象存在關係時, 就會作出對應的操做 ​

級聯更新

級聯刪除

刪除一邊數據時,同時將另外一邊的數據一併刪除

不設置級聯刪除

​ 默認:先把外鍵改成空,而後再刪除

​ 發送的SQL語句

設置級聯刪除

示例代碼

配置文件

在雙向級聯的過程中,會產生一些多餘的sql語句

緣由 ​ 當雙向維護時,兩都都維護了外鍵,當作更新操做時, 兩邊的外鍵都要去修改

解決辦法

1.使用單向維護 ​ 有些地方仍是會有問題 2.一方放棄維護權 ​ 在一的一方放棄外鍵維護權 ​ 在配置文件當中添加一個inverse="false/true" ​ true爲放棄外鍵維護權,false爲不放棄外鍵維護權

cascade與inverse

​ cascade控制有沒有關聯對象 ​ inverse控制有沒有外鍵 ​ 示例

lazy懶加載(默認值是proxy,不自動獲取外鍵對象)

改爲false,獲取外鍵對象

在linkman.hbm.xml

<many-to-one  name="customer"   class="com.myxq.domain.Customer"   column="link_cust_id"    lazy="false"/>

級聯保存或更新(解決 瞬時對象異常,只保存一邊)

在customer.hbm.xml

<set name="linkmens" cascade="save-update,delete" inverse="true">
	<!--set屬性名稱-->
    <key column="link_cust_id"></key><!--外鍵-->
    <one-to-many class="com.myxq.domain.Linkman">
    </one-to-many>
</set>

多對多

多對多關係配置

創建表

用戶表,一個用戶能夠有多個角色 ​

CREATE TABLE `user` (
				  `user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用戶id',
				  `user_code` varchar(32) NOT NULL COMMENT '用戶帳號',
				  `user_name` varchar(64) NOT NULL COMMENT '用戶名稱',
				  `user_password` varchar(32) NOT NULL COMMENT '用戶密碼',
				  `user_state` char(1) NOT NULL COMMENT '1:正常,0:暫停',
				  PRIMARY KEY (`user_id`)
				) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

角色表,一個角色能夠被多個用戶選擇

CREATE TABLE `role` (
				  `role_id` bigint(32) NOT NULL AUTO_INCREMENT,
				  `role_name` varchar(32) NOT NULL COMMENT '角色名稱',
				  `role_memo` varchar(128) DEFAULT NULL COMMENT '備註',
				  PRIMARY KEY (`role_id`)
				) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

關係圖

創建ORM

  • 用戶
  • 角色

Role.java

import lombok.Getter;
import lombok.Setter;
import java.util.HashSet;
import java.util.Set;
@Setter@Getter
public class Role {
    private Long role_id;
    private String role_name;
    private String role_memo;
    //角色下面的全部用戶
    private Set<User> users = new HashSet<>();
}

添加配置文件

用戶

角色

在覈心配置文件當中添加兩個新配置

編寫測試類

單向維護

雙向維護

雙向維護時,必需要有一方放棄外鍵維護 若是兩邊都有維護的話, 就會有重複的的記錄,因爲關係表是兩個字段做爲共同主鍵,不能有相同的記錄 解決辦法 ​ 一般都是讓被動方放棄,用戶選角色,角色爲被動方

多對多的級聯操做和一對多的級聯操做是同樣的

多對多的操做

關係的操做,只須要操做集合,就能夠操做它們之間的關係 給用戶添加一個新的角色

修改一個用戶的角色

刪除角色

查詢方式

OID查詢

什麼是OID查詢

  • 根據對象的OID主鍵進行檢索

OID查詢方式

  • get方法
  • load方法

對象導航查詢

什麼是對象導航檢索

  • Hibernate根據一個已經查詢到的對象,得到其關聯的對象的一種查詢方式
  • 先查詢到聯繫人,就能夠經過聯繫人獲取聯繫人所關聯的客戶對象

有點像級聯查詢

HQL

什麼是HQL

  • HQL查詢:Hibernate Query Language,Hibernate的查詢語言
  • 是一種面向對象的方式的查詢語言,語法相似SQL。
  • 經過session.createQuery(),用於接收一個HQL進行查詢方式。
  • 注意:使用時,不能用*,對於表,要採用別名查詢

查詢

簡單查詢

別名查詢

排序查詢

條件查詢

​ 位置綁定:根據參數的位置進行綁定條件

​ 名稱綁定:把參數對應的值起一個名稱 再去設置名稱

投影查詢

​ 查詢對象的某個或某些屬性 ​ 單個屬性

​ 多個屬性

​ 查詢多個屬性,封裝到對象當中 ​ 要在類中,提供構造方法

分頁查詢

統計查詢

​ 查詢的結構只有一個

分組查詢

多表查詢

​ 普通內鏈接

​ 迫切內鏈接 ​ ​ 經過hibernate將另外一個對象的數據,封裝該對象中

​ 在普通內鏈接inner join 後添加一個關鍵字fetch

QBC

什麼是QBC

​ Query By Criteria,條件查詢。是一種更加面向對象化的查詢的方式。

查詢

簡單查詢

排序查詢

分頁查詢

條件查詢

條件
=   eq
> gt
> =  ge
<  lt
<=  le
<> ne
like
in
and
or
單個條件

多個條件

統計查詢

離線條件查詢
  • 脫離Session,添加條件
  • 能夠在外部提早使用DetachedCriteria對象提交設置好條件
  • 最後再綁定到session當中

相關文章
相關標籤/搜索