Hibernate学习2 - 懒加载(延迟加载)、动态SQL参数、缓存

x33g5p2x  于2022-06-27 转载在 其他  
字(12.5k)|赞(0)|评价(0)|浏览(577)

懒加载 == 默认开启懒加载

概述

懒加载: 当Bean对象在代码层面设置了级联查询即 一对多、多对多、多对一的关系,查询某个Bean时,不会发送两条SQL,而是只发送一条SQL,当代码需要访问该Bean的级联数据时,在发送获取级联数据SQL。

代码 == lazy属性值

one-to-many标签

概述

lazy属性值1. true:默认值,开启懒加载1. false:关闭懒加载1. extra:更智能的懒加载

true/false

SysUser.java

@Getter
@Setter
public class SysUser extends BaseEntity {
    private static final long serialVersionUID = 2095940921263481761L;

    Set<Article> articles;

    /** 用户昵称 - 如果没有设置昵称直接使用账户名显示 */
    private String nickName;

    /** 头像图片地址 */
    private String headUrl;

    /** 账户 */
    private String loginName;

    /** 密码 */
    private String password;

    /** 手机号 */
    private String phoneNumber;

    /** 邮箱 */
    private String email;

    /** 性别 */
    private Integer gender;

    /** 个性签名 */
    private String personalMotto;

    /** 最近登录时间 - 格式 - yyyyMMddHHmmss */
    private String lastLoginTime;

    /** 登录状态:0未登录 1单设备登陆  2多设备登陆 */
    private Integer loginStatus;

    /** 账户禁用状态:0账户可使用  1账户不可使用(封号) */
    private Integer disabledStatus;

    @Override
    public String toString() {
        return "SysUser{" +
                "nickName='" + nickName + '\'' +
                ", headUrl='" + headUrl + '\'' +
                ", loginName='" + loginName + '\'' +
                ", password='" + password + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                ", email='" + email + '\'' +
                ", gender=" + gender +
                ", personalMotto='" + personalMotto + '\'' +
                ", lastLoginTime='" + lastLoginTime + '\'' +
                ", loginStatus=" + loginStatus +
                ", disabledStatus=" + disabledStatus +
                '}';
    }
}

Article.java

@NoArgsConstructor
@AllArgsConstructor
@Builder
@Accessors(chain = true)
@Data
public class Article extends BaseEntity {

    private static final long serialVersionUID = -4714261187453073302L;

    private SysUser sysUser;

    /** 文章标题 */
    private String title;

    /** 文章内容 */
    private String content;

    private String abbreviationContent;

    /** 文章被查看次数 */
    private Integer checkNum;

    /** 当前文章被点赞数 */
    private Integer likeNum;

    /** 当前文章不喜欢数 */
    private Integer notLikeNum;

    /** 文章是否违规:0未违规 1违规 - 违规不可显示 */
    private Integer isViolation;

    /** 创建者 - 冗余字段 - user表的nickName */
    private String createBy;

    /**列表文章的图片显示 - 如果指定则使用指定的图片(功能未做),没有指定则使用文章第一张图片,在没有则使用文章中有图标则使用目录分裂的图片*/
    private String imgUrl;

    /**文章内部图片*/
    private String imgUrls;

    /**文章内容类型:1富文本 2Markdown 3留空*/
    private String type;

    /**文章状态;-1违规 0草稿 1发布且公开  2发布且私密*/
    private String status;

}

SysUser.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="top.linruchang.entity.SysUser" table="sys_user">
        <id name="id" type="java.lang.String">
            <column name="id"></column>
            <!--插入时,如果你没有设置ID,会帮你自动添加ID-->
            <generator class="uuid"></generator>
        </id>

        <property name="headUrl" type="java.lang.String">
            <column name="head_url" ></column>
        </property>

        <property name="loginName" type="java.lang.String">
            <column name="login_name" ></column>
        </property>

		<!--默认是开启懒加载,测试时自行切换查看效果-->
        <set name="articles" table="article" lazy="false">
            <key column="user_id"></key>
            <one-to-many class="top.linruchang.entity.Article"></one-to-many>
        </set>

    </class>
</hibernate-mapping>

Article.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="top.linruchang.entity.Article" table="article">
        <id name="id" type="java.lang.String">
            <column name="id" ></column>
            <!--插入时,如果你没有设置ID,会帮你自动添加ID-->
            <generator class="uuid"></generator>
        </id>

        <!--<property name="userId" type="java.lang.String">-->
        <!--    <column name="user_id"></column>-->
        <!--</property>-->

        <property name="title" type="java.lang.String">
            <column name="title"></column>
        </property>

        <property name="content" type="java.lang.String">
            <column name="content"></column>
        </property>

        <property name="likeNum" type="java.lang.Integer">
            <column name="like_num"></column>
        </property>

        <!--默认是开启懒加载,测试时自行切换查看效果,如果这里显示lazy=true则会报错-->
        <many-to-one lazy="false" name="sysUser" column="user_id" class="top.linruchang.entity.SysUser"  />

    </class>
</hibernate-mapping>

MyTest2.java

public class MyTest2 {

    @SneakyThrows
    public static void main(String[] args) {

        new Thread(() -> {
            Configuration configure = new Configuration().configure();

            //获取sessionFactory
            SessionFactory sessionFactory = configure.buildSessionFactory();
            //获取数据库连接session
            Session session = sessionFactory.openSession();
            SysUser sysUser = session.find(SysUser.class, "6d72c93aa292cf2ca2e789919a5e7bdc");

            System.out.println(sysUser);
        }).start();

        Thread.sleep(10000);

    }

}

extra

比true/fasle属性更加懒惰的一种加载方式,或者可以说更加智能的一样加载方式,如果你只需要集合的长度,hibernate会查count而不是查整个数据集,当你使用到数据时,在会查数据集*

SysUser.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="top.linruchang.entity.SysUser" table="sys_user">
        <id name="id" type="java.lang.String">
            <column name="id"></column>
            <!--插入时,如果你没有设置ID,会帮你自动添加ID-->
            <generator class="uuid"></generator>
        </id>

        <property name="headUrl" type="java.lang.String">
            <column name="head_url" ></column>
        </property>

        <property name="loginName" type="java.lang.String">
            <column name="login_name" ></column>
        </property>

        <!--更加懒惰的加载方式开启-->
        <set name="articles" table="article" lazy="extra">
            <key column="user_id"></key>
            <one-to-many class="top.linruchang.entity.Article"></one-to-many>
        </set>

    </class>
</hibernate-mapping>

测试

@Test
    public void test6() throws InterruptedException {

        Configuration configure = new Configuration().configure();

        //获取sessionFactory
        SessionFactory sessionFactory = configure.buildSessionFactory();
        //获取数据库连接session
        Session session = sessionFactory.openSession();
        SysUser sysUser = session.find(SysUser.class, "6d72c93aa292cf2ca2e789919a5e7bdc");

        System.out.println(sysUser.getArticles().size());

        System.out.println("============================");

        System.out.println(sysUser.getArticles());
        
    }

many-to-one标签

概述

lazy属性值false:关闭懒加载proxy:代理,懒加载模式。调用方法访问到one变量,都是发送SQL语句查询one的对象no-proxy:不代理,懒加载模式,调用方法是否访问到one变量,都是发送SQL查询one对象这两种随便选一个吧,问题不大,我也没搞懂区别

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="top.linruchang.entity.Article" table="article">
        <id name="id" type="java.lang.String">
            <column name="id" ></column>
            <!--插入时,如果你没有设置ID,会帮你自动添加ID-->
            <generator class="uuid"></generator>
        </id>

        <!--<property name="userId" type="java.lang.String">-->
        <!--    <column name="user_id"></column>-->
        <!--</property>-->

        <property name="title" type="java.lang.String">
            <column name="title"></column>
        </property>

        <property name="content" type="java.lang.String">
            <column name="content"></column>
        </property>

        <property name="likeNum" type="java.lang.Integer">
            <column name="like_num"></column>
        </property>
        
        <!-- 自己去调整这个属性,默认是开启了懒加载模式的 --> 
        <many-to-one lazy="no-proxy" name="sysUser" column="user_id" class="top.linruchang.entity.SysUser" />

    </class>
</hibernate-mapping>

many-to-many标签 == 跟 one-to-many一样

概述

lazy属性值1. true:默认值,开启懒加载1. false:关闭懒加载1. extra:更智能的懒加载

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="top.linruchang.entity.MyOrder2" table="my_order">
        <id name="id" type="java.lang.String">
            <column name="id"></column>
            <!--插入时,如果你没有设置ID,会帮你自动添加ID-->
            <generator class="uuid"></generator>
        </id>

        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <property name="money" type="java.lang.String">
            <column name="money"></column>
        </property>

        <!-- 这里进行设置懒加载-->
        <set name="myUser2" table="user_order_rel" lazy="extra">
            <key column="my_order_id" ></key>
            <many-to-many column="my_user_id" class="top.linruchang.entity.MyUser2"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

动态SQL参数 = 默认不开启

insert = 跟MyBatisPlus一样,属性字段是空则该字段不会出现在SQL中

update = 跟MyBatisPlus不一样,根据缓存的对象来判断属性字段是否需要出现在SQL中,属性字段缓存值与当前对象不一致则出现在SQL,否则不出现

Article.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!-- package:类似mybatis的Bean别名type-aliases-package这个属性,用于有些属性不用写全限定名-->
<!-- default-lazy:默认启动懒加载,即一对多,多对多,多对一关系上使用-->
<!-- auto-import:默认true,是否可以在查询语句中使用非全限定名,如果项目中有两个同名的Bean,最好在两个映射文件中设置为false-->
<hibernate-mapping package="top.linruchang.entity"  default-lazy="true" auto-import="false" >

    <!-- dynamic-insert dynamic-update:默认都为false。true时类似 mybatisplus的代码插入Java语句,只要属性是空则update、insert的SQL语句就不会出现该列 -->
    <class name="Article" table="article" dynamic-insert="true" dynamic-update="true">
        <id name="id" type="java.lang.String">
            <column name="id" ></column>
            <!--插入时,如果你没有设置ID,会帮你自动添加ID-->
            <generator class="uuid"></generator>
        </id>

        <!--<property name="userId" type="java.lang.String">-->
        <!--    <column name="user_id"></column>-->
        <!--</property>-->

        <property name="title" type="java.lang.String">
            <column name="title"></column>
        </property>

        <property name="content" type="java.lang.String">
            <column name="content"></column>
        </property>

        <property name="likeNum" type="java.lang.Integer">
            <column name="like_num"></column>
        </property>

        <many-to-one lazy="no-proxy" name="sysUser" column="user_id" class="SysUser" />

    </class>
</hibernate-mapping>

测试程序

@Test
    public void test6() {

        Configuration configure = new Configuration().configure();
        SessionFactory sessionFactory = configure.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        //查到的结果会被session缓存
        Article article = session.find(Article.class, "4028b88178e54c750178e54c77c80000");
        System.out.println(article);

        // 动态update=true情况下:拿上面的缓存与当前对象做比较
        article.setTitle("放到沙发上对方的身份==");
        session.saveOrUpdate(article);
        
        //如果使用这样,最后会save的,因为判断是否需要insert、update是根据缓存去看的
        // Article updateArticle = new Article();
        // updateArticle.setId(article.getId())
        // updateArticle.setContent("fdsfdsfsd");
       //  session.saveOrUpdate(updateArticle);

        transaction.commit();
        session.close();

    }

未开启动态更新SQL

开启动态更新SQL

缓存

一级缓存Session级别 = 默认开启

@Test
    public void test6() {

        Configuration configure = new Configuration().configure();
        SessionFactory sessionFactory = configure.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        
        
        Article article = session.find(Article.class, "4028b88178e54c750178e54c77c80000");
        System.out.println(article);
        Article article2 = session.find(Article.class, "4028b88178e54c750178e54c77c80000");
        System.out.println(article2);

        transaction.commit();
        session.close();

    }

相关文章