学习hibernate(二) -- session缓存

    session对象是操作数据库的主要接口,可以对数据库进行保存、更新和删除等一系列的操作,并且可以将数据库中的数据加载到java对象中。

    session对象中有一个缓存,是session级别的,也称之为一级缓存。缓存中存储的java对象被称之为持久化对象。持久化对象和数据库中的相关记录相互对应。

    看一段代码:

    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;

    @Before
    public void onLoad() {
        // 0.创建configuration对象,该对象保存着hibernate的配置信息和对象关系映射的信息。
        Configuration cfg = new Configuration().configure();
        // 1.创建sessionfactory对象
        StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
                .applySettings(cfg.getProperties());
        StandardServiceRegistry registry = builder.build();
        sessionFactory = cfg.buildSessionFactory(registry);
        // 2.创建session对象
        session = sessionFactory.openSession();
        // 3.开始事务
        transaction = session.beginTransaction();
    }

    @After
    public void onUnLoad() {
        // 1.提交事务
        transaction.commit();
        // 2.关闭session对象
        session.close();
        // 3.关闭sessionfactory对象
        sessionFactory.close();
    }

    @Test
    public void test() {
        User user = (User)session.load(User.class, 1);
        System.out.println(user);
        //    第二次get时,是从session cache中获得的。
        User user2 = (User)session.load(User.class, 1);
        System.out.println(user2);
    }

    210548_LJz6_2450666.png

    可以看到从数据库中查询了2次user对象,只输出了一条sql语句。第二次的get操作实际上是从缓存中获得的user对象,并没有从对数据库进行select查询。缓存减少了对数据库的操作。

    缓存与数据库之间可以通过某些方法互相同步,session可以提取缓存中的对象向数据库进行操作,也可以将提取数据库中的记录来更新缓存中的对象。还可以对session缓存进行清空。

    常用的操作session缓存的方法有3个,它们分别是:

  • flush

    当调用flush方法时,session将保证缓存中的对象与数据表中的记录一致。也就是说,若缓存中的对象与数据库表中的记录不一致,则会发送update语句更新数据库。

    若不显示调用flush方法,当事务进行commit的时候会自动的调用一次flush方法。

    当然也有例外,在同一个事务中使用QBC或HQL语句也会隐士调用一次flush方法。

  • refresh

    当调用refresh方法时,其实与flush大致相反。若缓存中的对象与数据库表中的记录不一致,则会发送一个select语句来更新session缓存中的对象。

  • clear

    当调用clear的时候,将清空session缓存中的对象。

    进行一些测试,来测试一下这几个方法,首先是flush方法:

    @Test
    public void testSessionFlush() {
        //    从数据库中加载一个对象。
        User user = (User)session.get(User.class, 1);
        user.setName("Kobe");
        System.out.println(user);
    }

    数据库中的保存的Name是"Jack"这个值,get到User对象后,进行一次set,然后commit后会发现生成了一条update语句,数据库中的值也改变了,这就是flush方法起到的作用,控制台输出如下图:

213251_WmJX_2450666.png

213251_Giuz_2450666.png

     接下来测试一下refresh方法,写一段代码:

    @Test
    public void testSessionRefresh() {
        User user = (User)session.get(User.class, 1);
        System.out.println(user);
        session.refresh(user);
        User user2 = (User)session.get(User.class, 1);
        System.out.println(user);
    }

    在session.refresh(user)处打一个短点,在程序暂停后,去数据库中手动修改name字段的值,在调用refresh方法后看看是否数据库的值会更新缓存中对象的值,操作过程如下:

214323_4sXl_2450666.png

    程序运行到refresh方法之前,进行一次get,并且进行了输出。可以看到控制台输出了select和user的值。之后进入断点等待继续。

214323_rmJH_2450666.png

    手动修改了数据库中name字段的值,将"Kobe"改成了"Mark"。

214324_OF5G_2450666.png

    断点向下一步,执行了refresh,可以看到控制台又输出了一条select语句。说明对手动修改了数据库中的数据后,与session缓存中的对象不一致了。需要获取数据库中的数据对持久化对象进行覆盖。于是执行了一次select语句。

214324_rjqR_2450666.png

    最后输出结构,这里可以看到虽然执行了select语句,但是并没有改变持久化对象中的数据。这是由于hibernate的事务隔离机制导致的。一共有4个隔离级别,分别是:

  • READ UNCOMMITED = 1

  • READ COMMITED = 2

  • REPEATABLE READ = 4

  • SERIALIZEABLE = 8

    可以在配置文件中将隔离级别hibernate.connection.isolation设置成2,这样refresh就会有预期的效果。

<!-- 设置hibernate的事务隔离机制 -->
<property name="hibernate.connection.isolation">2</property>

    设置后在进行一次测试,结果如下:

220309_2Fw9_2450666.png

    当改变隔离级别后,先修改数据库的值,在调用refresh方法,则会立即更新持久化对象。

    最后测试一下clear方法,该方法会清空session的缓冲区:

    @Test
    public void testSessionClear() {
        User user = (User)session.get(User.class, 1);
        session.clear();
        User user2 = (User)session.get(User.class, 1);
    }

    最初测试session缓存时,在一个事务中第二次调用get方法加载同一个对象,不会发送select语句到数据库进行查询。而在第二次调用get方法前,调用一次clear方法,则会清空session缓冲区中的持久化对象,在次调用get又需要到数据库进行select操作,控制台输出的sql如下:

220711_w5a6_2450666.png

    可以看到有两个select语句被打印,证明了clear会清空缓冲区中的持久化对象。

    以上就是常用的操作session缓冲区的三个方法的测试。

转载于:https://my.oschina.net/u/2450666/blog/646958

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值