• HIbernate多表学习


    一,表与表之间关系:

    1.一对多:多的表用一个外键存一的表的主键id。
    在这里插入图片描述

    2.多对多:新建第三张表,两个外键分别存两个多的表的主键id。
    在这里插入图片描述
    3.一对一

    二,Hibernate一对多练习:

    一对多映射配置(以客户和联系人,客户是一,联系人是多为例子):
    1,创建两个实体类,客户和联系人
    2,让两个实体类之间互相表示
    (1)在客户实体类里面表示多个联系人(一个客户里面有多个联系人)
    Customer.java:
    在这里插入图片描述

    package com.myHibernate.entity;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 客户实体类
     * @author AUAS
     */
    public class Customer {
        /**
         * Hibernate要求实体类要有一个属性是唯一的,类似与数据库表的主键
         */
        private Integer id;
        private String cusName;
        private String cusPhone;
    
        //在客户实体类里面表示多个联系人,一个客户有多个联系人
        //hibernate要求使用集合表示多的数据,使用set集合
        private Set<LinkUser> linkUser = new HashSet<LinkUser>();
    
        public Set<LinkUser> getLinkUser() {
            return linkUser;
        }
    
        public void setLinkUser(Set<LinkUser> linkUser) {
            this.linkUser = linkUser;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getCusName() {
            return cusName;
        }
    
        public void setCusName(String cusName) {
            this.cusName = cusName;
        }
    
        public String getCusPhone() {
            return cusPhone;
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    (2)在联系人实体类里面表示所属客户(一个联系人只能属于一个客户)
    LinkUser.java:
    在这里插入图片描述

    package com.myHibernate.entity;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 客户实体类
     * @author AUAS
     */
    public class LinkUser {
        /**
         * Hibernate要求实体类要有一个属性是唯一的,类似与数据库表的主键
         */
        private Integer id;
        private String linkName;
        private String linkPhone;
    
        //在联系人实体类里面表示所属客户,一个联系人只能属于一个客户
        private Customer customer;
    
        public Customer getCustomer() {
            return customer;
        }
    
        public void setCustomer(Customer customer) {
            this.customer = customer;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getLinkName() {
            return linkName;
        }
    
        public void setLinkName(String linkName) {
            this.linkName = linkName;
        }
    
        public String getLinkPhone() {
            return linkPhone;
        }
    
        public void setLinkPhone(String linkPhone) {
            this.linkPhone = linkPhone;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    3,配置映射关系
    (1)一般一个实体类对应一个映射文件
    (2)把实体类最基本的配置完成
    (3)在映射文件中,配置一对多关系
    (3.1)在客户映射文件中,表示所有的联系人。
    Costomer.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>
        <!-- 1 配置类和表对应
            class标签
            name属性:实体类全路径
            table属性:数据库表名称
        -->
        <class name="com.myHibernate.entity.Customer" table="t_customer">
            <!-- 2 配置实体类id和表id对应
                hibernate要求实体类有一个属性唯一值
                hibernate要求表有字段作为唯一值
            -->
            <!-- id标签
                name属性:实体类里面id属性名称
                column属性:生成的表字段名称
             -->
            <id name="id" column="id">
                <!-- 设置数据库表id增长策略
                    native:生成表id值就是主键自动增长
                -->
                <generator class="native"></generator>
            </id>
            <!-- 配置其他属性和表字段对应
                name属性:实体类属性名称
                column属性:生成表字段名称
            -->
            <property name="cusName" column="cusName"></property>
            <property name="cusPhone" column="cusPhone"></property>
    
            <!-- 在客户映射文件中,表示所有联系人
                 使用set标签表示所有联系人
                 set标签里面有name属性:name属性值与客户实体类里面表示联系人的集合名称一样-->
            <set name="linkUser">
                <!--    一对多建表,有外键
                        hibernate机制:双向维护外键,在一和多那一方都配置外键
                        column属性值:外键名称(即customer表存对应的LinkUser表的id)
                 -->
                <key column="cusId"></key>
                <!--     客户所有的联系人,class里面写联系人实体类的全路径       -->
                <one-to-many class="com.myHibernate.entity.LinkUser"></one-to-many>
            </set>
        </class>
    </hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    (3.2)在联系人映射文件中,表示所属客户
    LinkUser.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>
        <!-- 1 配置类和表对应
            class标签
            name属性:实体类全路径
            table属性:数据库表名称
        -->
        <class name="com.myHibernate.entity.LinkUser" table="t_link_user">
            <!-- 2 配置实体类id和表id对应
                hibernate要求实体类有一个属性唯一值
                hibernate要求表有字段作为唯一值
            -->
            <!-- id标签
                name属性:实体类里面id属性名称
                column属性:生成的表字段名称
             -->
            <id name="id" column="id">
                <!-- 设置数据库表id增长策略
                    native:生成表id值就是主键自动增长
                -->
                <generator class="native"></generator>
            </id>
            <!-- 配置其他属性和表字段对应
                name属性:实体类属性名称
                column属性:生成表字段名称
            -->
            <property name="linkName" column="linkName"></property>
            <property name="linkPhone" column="linkPhone"></property>
    
            <!--   表示联系人所属客户
                    names属性:属性值与联系人LinkUser实体类表示客户的名称一致
                    class属性:customer实体类全路径
                    column属性:外键名称-->
            <many-to-one name="customer" class="com.myHibernate.entity.Customer" column="cusId"></many-to-one>
        </class>
    </hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    4.创建核心配置文件,把映射文件引入到核心配置文件中
    hibernate.cfg.xml:
    在这里插入图片描述
    5.一对多级联保存:

    三,HIbernate多对多操作:

    多对多映射配置:
    以用户和角色为例(一个用户可以有多个角色,一个角色可以有多个用户)
    1.创建实体类,用户实体类和角色实体类
    2.两个实体类之间互相表示
    (1)一个用户里面有多个角色,使用set集合
    (2)一个角色有多个用户,使用set集合

    四,Hibernate查询方式:

    1.对象导航查询:
    (1)根据id查询某个客户,再查询这个客户里面所有联系人
    2.OID查询:
    (1)根据id查询某一条记录,返回对象
    3.hql查询:
    (1)Query对象,写hql语句实现查询
    4.QBC查询:
    (1)Criteria对象
    5.本地sql查询:
    (1)SQLQuery对象,使用普通sql实现查询
    对象导航查询:
    1.查询某个客户里面所有联系人过程,使用对象导航实现
    在这里插入图片描述

    package cn.itcast.hibernatetest;
    
    import com.myHibernate.entity.Customer;
    import com.myHibernate.entity.LinkUser;
    import com.myHibernate.entity.User;
    import com.myHibernate.utils.HibernateUtils;
    import org.hibernate.SQLQuery;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.junit.Test;
    
    import java.util.List;
    import java.util.Set;
    
    public class HibernateDemo {
    
        @Test
        public void testSelect() {
            SessionFactory sessionFactory = null;
            Session session = null;
            Transaction transaction = null;
            try {
                sessionFactory = HibernateUtils.getSessionFactory();
                //提供返回与本地线程的session的方法
                session = HibernateUtils.getSessionObject();
                //开启事务
                transaction = session.beginTransaction();
    
                //演示对象导航查询
                //查询cid=1客户,再查询这个客户的所有联系人
                Customer customer = session.get(Customer.class,1);
                //再查询这个客户里面所有联系人(直接得到客户里面联系人的set集合)
                Set<LinkUser> linkUsers = customer.getLinkUser();
    
                System.out.println(linkUsers.size());
    
                //提交事务
                transaction.commit();
            } catch (Exception e) {
                e.printStackTrace();
                //回滚事务
                transaction.rollback();
            } finally {
                //关闭操作
    //            session.close();
    //            sessionFactory.close();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    OID查询:
    1.根据id查询记录
    (1)调用session里面的get方法实现
    在这里插入图片描述
    HQL查询:
    1.hql:hibernate query language ,是hibernate提供的一种查询语言,hql语言喝普通sql很相似。
    区别:普通sql操作数据库表喝字段;hql操作实体类和属性
    2.常用的hql语句(使用hql查询操作时候,使用Query对象)
    (1)查询所有数据( from 实体类名称
    (1.1)创建Query对象,写hql语句
    (1.2)调用Query对象里面的方法得到结果
    在这里插入图片描述
    (2)条件查询
    (2.1)hql条件查询语句写法:
    from 实体类名称 where 实体类属性名称 = ? and 实体类属性名称 = ?
    from 实体类名称 where 实体类属性名称 like ?
    在这里插入图片描述
    在这里插入图片描述
    (3)排序查询
    (3.1)hql排序语句写法
    from 实体类名称 order by 实体类属性名称 asc / desc
    在这里插入图片描述

    (4)分页查询
    (4.1)mysql实现分页(使用关键字limit实现)
    在这里插入图片描述
    (4.2)在hql中实现分页(在hql中的语句不能写limit。hibernate的Query对象封装两个方法实现分页操作)
    在这里插入图片描述
    (5)投影查询
    (5.1)投影查询(即查表中的某个(某些)字段,不是查询所有字段
    sql语句:
    在这里插入图片描述
    (5.2)投影查询的hql语句写法:
    select 实体类属性名称1,实体类属性名称2 from 实体类名称
    注意:hql语句的select 后面不能像sql语句一下写 * 查所有。
    在这里插入图片描述
    (6)聚集函数使用
    (6.1)常用的聚集函数(count ,sum, avg ,max ,min)
    (6.2)hql聚集函数的写法
    在这里插入图片描述

    package cn.itcast.hibernatetest;
    
    import com.myHibernate.entity.Customer;
    import com.myHibernate.entity.LinkUser;
    import com.myHibernate.entity.User;
    import com.myHibernate.utils.HibernateUtils;
    import org.hibernate.*;
    import org.junit.Test;
    
    import java.util.List;
    import java.util.Set;
    
    public class HibernateDemo {
    
        @Test
        public void testSelect() {
            SessionFactory sessionFactory = null;
            Session session = null;
            Transaction transaction = null;
            try {
                sessionFactory = HibernateUtils.getSessionFactory();
                //提供返回与本地线程的session的方法
                session = HibernateUtils.getSessionObject();
                //开启事务
                transaction = session.beginTransaction();
    
                //演示hql 条件查询
                //创建Query对象
    //            Query query = session.createQuery("FROM Customer As c Where c.cusName like ?");
    //            //设置条件值,向?里面设置值
    //            //setParameter方法两个参数(第一个参数:int类型是?位置,?位置从0开始。第二个参数:具体参数值)
    //            query.setParameter(0,"%小%");//设置第一个问号的值为2
    //            //调用方法得到结果
    //            List<Customer> customerList = query.list();
    //            for (Customer customer : customerList) {
    //                System.out.println(customer.getCusName()+":"+customer.getCusPhone());
    //            }
    
    //            //演示hql 排序查询
    //            //创建Query对象
    //            Query query = session.createQuery("FROM Customer ORDER BY id DESC");
    //            //设置条件值,向?里面设置值
    //            //调用方法得到结果
    //            List<Customer> customerList = query.list();
    //            for (Customer customer : customerList) {
    //                System.out.println(customer.getCusName()+":"+customer.getCusPhone());
    //            }
    
    //            //演示分页查询
    //            //创建Query对象
    //            Query query = session.createQuery("FROM Customer");
    //            //设置分页数据
    //            query.setFirstResult(0); //设置分页开始位置
    //            query.setMaxResults(2); //设置每页记录数
    //            //调用方法得到结果
    //            List<Customer> customerList = query.list();
    //            for (Customer customer : customerList) {
    //                System.out.println(customer.getCusName()+":"+customer.getCusPhone());
    //            }
    
    //            //演示投影查询
    //            //创建Query对象
    //            Query query = session.createQuery("SELECT cusName FROM Customer");
    //            //调用方法得到结果
    //            List<Object> cusNameList = query.list();
    //            for (Object cusName: cusNameList) {
    //                System.out.println(cusName);
    //            }
    
                //演示聚集函数
                //创建Query对象
                Query query = session.createQuery("SELECT COUNT(*) FROM Customer");
                //调用方法得到结果
                //query对象里面有方法,直接返回对象形式
                Object number = query.uniqueResult();
                //放回int类型
                //首先吧Object变成long类型,再变成int类型
                Long longNumber = (Long)number;
                int count = longNumber.intValue();
                System.out.println(count);
    
                //提交事务
                transaction.commit();
            } catch (Exception e) {
                e.printStackTrace();
                //回滚事务
                transaction.rollback();
            } finally {
                //关闭操作
    //            session.close();
    //            sessionFactory.close();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    QBC查询:

    1.使用hql查询需要写hql语句实现,但是使用qbc时候,不需要写语句了,使用方法实现。
    2.使用qbc时候,操作实体类和属性。
    3.使用qbc,使用Criteria对象实现
    (1)查询所有:
    (1.1)创建Criteria对象(session.createCriteria(Customer.class))
    (1.2)调用方法得到结果
    在这里插入图片描述
    (2) 条件查询:
    没有语句,使用封装的方法实现(criteria.add(Restrictions.eq(“id”,2));
    在这里插入图片描述
    在这里插入图片描述

    (3)排序查询:
    在这里插入图片描述
    在这里插入图片描述
    (4) 分页查询
    开始位置计算公式:(当前页-1)* 每页记录数
    在这里插入图片描述
    (5)统计查询:
    在这里插入图片描述
    (6)离线查询:
    (6.1)servlet调用service,service调用dao
    (6.11)在dao里面对数据库crud操作
    (6.12)在dao里面使用hibernate框架,使用hibernate框架时候,调用session里面的方法实现功能
    在这里插入图片描述

    HQL多表查询:

    mysql里面多表查询:
    在这里插入图片描述
    1.HQL内连接查询:
    (1)内连接查询hql语句写法 from Customer c inner join c.linkUser
    在这里插入图片描述
    返回list,list里面每部分是数组形式
    在这里插入图片描述
    (2)迫切内连接
    (2.1)迫切内连接和内连接底层实现是一样的
    (2.2)区别:使用内连接返回list中每部分是数组,迫切内连接返回list每部分是对象
    (2.3)hql语句写法 from Customer c inner join fetch c.linkUser
    在这里插入图片描述
    返回list,list里面每部分是对象形式
    在这里插入图片描述

    2.HQL左外连接查询:
    (1)左外连接hql语句: from Customer c left outer join c.linkUser
    在这里插入图片描述
    在这里插入图片描述
    (2)迫切左外连接hql语句: from Customer c left outer join fetch c.linkUser
    在这里插入图片描述
    在这里插入图片描述

    注意:左外连接返回list中每部分是数组,迫切左外连接返回list每部分是对象

    3.右外连接hql语句:
    from CUstomer c right outer join c.linkUser

    HIbernate检索策略:

    检索策略的概念:
    1.hibernate检索策略分为两类:
    (1)立即查询:根据id查询,调用get方法,一调用get方法马上发送语句查询数据库
    在这里插入图片描述

    (2)延迟查询:根据id查询,还有load方法,调用load方法不会马上发送语句查询数据,只有得到对象里面的值的时候才会发送语句查询数据库。

    在这里插入图片描述

        @Test
        public void testSelect1() {
            SessionFactory sessionFactory = null;
            Session session = null;
            Transaction transaction = null;
            try {
                sessionFactory = HibernateUtils.getSessionFactory();
                //提供返回与本地线程的session的方法
                session = HibernateUtils.getSessionObject();
                //开启事务
                transaction = session.beginTransaction();
    
    //            //1.演示hibernate检索策略(立即查询)
    //            //查询id=1的客户信息(执行get方法之后,是否发送sql语句)
    //            //调用get方法马上发送sql语句查询数据库
    //            Customer customer = session.get(Customer.class,1);
    //            System.out.println(customer.getId());
    
                //2.演示hibernate检索策略(延迟查询)
                //查询id=1的客户信息(执行loda方法之后,是否发送sql语句)
                //调用load方法不会马上发送sql语句查询数据库
                //返回对象里面只有id值
                //得到对象里面不是id的其它值时候才会发送语句
                Customer customer = session.load(Customer.class,2);
                System.out.println(customer.getId());
                System.out.println(customer.getCusName());
    
                //提交事务
                transaction.commit();
            } catch (Exception e) {
                e.printStackTrace();
                //回滚事务
                transaction.rollback();
            } finally {
                //关闭操作
    //            session.close();
    //            sessionFactory.close();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    延迟查询分成两类:
    (1)类级别延迟:根据id查询返回实体类对象,调用load方法不会马上发送语句
    在这里插入图片描述
    (2)关联级别延迟:查询某个客户,再查询客户的所有联系人,查询客户的所有联系人的过程是否需要延迟,这个过程成为关联级别延迟。
    在这里插入图片描述
    关联级别延迟操作:
    1.在映射文件中进行配置实现(根据客户得到所有的联系人,在客户映射文件中配置)
    2.在set标签上使用属性(具体如下)
    在这里插入图片描述
    立即查询配置如下:
    在这里插入图片描述
    及其懒惰(需要什么查什么),延迟检索配置如下:
    在这里插入图片描述
    批量抓取:
    1.查询所有客户,返回list集合,遍历list集合,得到每个客户,得到每个客户的所有联系人。
    方法一:会查询多次数据库,性能不好
    在这里插入图片描述
    方法二:配置了批量抓取,性能好
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    类和对象收尾
    unity之粒子特效制作图片拼合文字效果
    开箱即用的工具函数库xijs更新指南(v1.2.6)
    【滤波跟踪】基于扩展卡尔曼滤波的无人机路径跟踪附matlab代码
    打破国外垄断|暴雨发布纯血国产电脑
    RestFul,会话技术,Fiddler
    进程调度算法之时间片轮转调度(RR),优先级调度以及多级反馈队列调度
    十三、Loss Functions
    xgp怎么取消续费 微软商店xgp会员取消自动续费详细教程
    qlib熟练使用后如何进阶?tests和examples
  • 原文地址:https://blog.csdn.net/weixin_45703155/article/details/127856987