学习hibernate(二) -- session缓存

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

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

    看一段代码:
数据库

    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);
    }

    

    能够看到从数据库中查询了2次user对象,只输出了一条sql语句。第二次的get操做其实是从缓存中得到的user对象,并无从对数据库进行select查询。缓存减小了对数据库的操做。
缓存

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

    经常使用的操做session缓存的方法有3个,它们分别是:app

  • flush测试

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

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

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

  • 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方法起到的做用,控制台输出以下图:

     接下来测试一下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方法后看看是否数据库的值会更新缓存中对象的值,操做过程以下:

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

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

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

    最后输出结构,这里能够看到虽然执行了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>

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

    当改变隔离级别后,先修改数据库的值,在调用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以下:

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

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

相关文章
相关标签/搜索