Hibernate id自动增长测试 及 二级缓存测试 及 缓存并发测试

签名:love聊网络那点事http://weibo.com/u/3923942488
1:内存溢出和id自增长测试测试代码如下

save方法执行之后但是没commit之前id也是在自动增加的:说明save访问了数据库并修改了id的值。

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="1000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="300"
        overflowToDisk="true"
        />
        <!--1:缓存可以存储的总记录量
            2:缓存是否永远不销毁
            3:当缓存闲置时间超过改时间时自动销毁缓存
            4:缓存的存活时间
            (如果3,4都设置了实际超时时间是3,4中的最小时间)
            5:当缓存中的数据达到最大值时,是否把缓存数据写入磁盘
         -->
        <cache name="sampleCache1"
        maxElementsInMemory="1000"  
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="300"
        overflowToDisk="true"
        />
</ehcache>

public void testUser(){
        long startTime = System.currentTimeMillis();
        //加载配置,构造sessionFactory对象
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        //获取会话
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        for(int i = 2000;i < 150000;i ++){
            User user = new User();
            user.setEmail("aa" + i);
            user.setUserIntegral(i);
            user.setPassword("a" + i);
            session.save(user);
            System.out.println("===");
            System.out.println(user.getId());
            System.out.println("++");
            //没有clear当到达120000左右时会出现内存溢出导出插入失败但是数据库中的id却一直在涨,这个暂时没弄明白是怎么回事。
//            if(i % 200 == 0){
//                session.flush();
//                session.clear();
//            }
        }
        transaction.commit();
        session.close();
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime);
    }

当在循环过程中通过mysql工具往数据插入数据时id是在增长的,说明save虽然没有将数据插入到数据库中,但是访问过数据库,并修改了id的值。

当commit时数据真正的插入到数据库中了。


2:二级缓存的测试

测试代码如下

//通过将User.hbm.xml中加上和移除    <cache usage="read-only" region="sampleCache1"/>来测试二级缓存的作用
//移除后打印两条查询语句,加上后只有一条查询语句


    @Ignore
    @Test
    public void testTran(){
        //加载配置,构造sessionFactory对象
        SessionFactory sessionFactory2 = new Configuration().configure().buildSessionFactory();
        //获取会话
        Session session2 = sessionFactory2.openSession();
        User user = (User) session2.load(User.class, 2);
        System.out.println(user.getNickname());
        //从session缓存即一级缓存中移除user对象
        session2.evict(user);
        
        //测试二级缓存超时:超时打印两条sql语句,缩短时间不超时打印一条sql语句,不从session缓存中移除的话超时不超时都打印一条sql语句。
        try {
            Thread.sleep(120000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("================");
        User user2 = (User) session2.load(User.class, 2);
        System.out.println(user2.getNickname());
        
        
        session2.close();
    }

encache.xml配置如下

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="1000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="300"
        overflowToDisk="true"
        />
        <!--1:缓存可以存储的总记录量
            2:缓存是否永远不销毁
            3:当缓存闲置时间超过改时间时自动销毁缓存
            4:缓存的存活时间
            (如果3,4都设置了实际超时时间是3,4中的最小时间)
            5:当缓存中的数据达到最大值时,是否把缓存数据写入磁盘
         -->
        <cache name="sampleCache1"
        maxElementsInMemory="1000"  
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="300"
        overflowToDisk="true"
        />
</ehcache>

3.二级缓存并发测试

测试代码:

    //不同的线程查询不能使用encache缓存,即不同的线程间encache是无效的。
//    @Ignore
    @Test
    public void test33() throws InterruptedException{
        //加上这两句则只执行一次查询否则执行四次查询
        User user = (User) session.load(User.class, 2);
        System.out.println(user.getNickname());
        Thread[] t = new Thread[4];
        for(int i = 0;i < t.length; i ++){
            t[i] = new Thread(new Runnable() {
                public void run() {
                    search();
                }
            });
        }
        for(int i = 0;i < t.length;i ++){
            t[i].start();
        }
        Thread.sleep(8000);
        session.close();
    }

4:二级缓存更新读取测试:还没有搞清楚 希望高人指点

    <cache usage="read-only" region="sampleCache1"/>

修改usage模式也更新失败。java.lang.UnsupportedOperationException: Can't write to a readonly object

测试代码:

   

    @Test
    public void test2(){
        //加载配置,构造sessionFactory对象
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        //获取会话
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        //二级缓存中缓存了这两个对象
        User user1 = (User) session.load(User.class, 2);
        User user2 = (User) session.load(User.class, 3);
        
        
        System.out.println("==============================");
        //修改了user2
        //load是延迟加载org.hibernate.LazyInitializationException: could not initialize proxy - no Session
        //所以需要下面两句输出语句
        System.out.println(user1.getEmail());
        System.out.println("ddddd:::::" + user2.getEmail());
        
        System.out.println("++++++++++++++");
        //将这两个对象从session缓存中清楚避免影响测试
         session.evict(user1);

        session.evict(user2);

//如果注释掉这两行即可以修改,也就是session缓存是支持修改的。因为session缓存供同一使用者用,而二级缓存是供所有人使用。


        user1.setEmail("update2");
        user1.setEmailVerify(true);
        session.update(user1);
        transaction.commit();// java.lang.UnsupportedOperationException: Can't write to a readonly object
        
        
//        //测试user3也就是user1是否从二级缓存中移除是否在二级缓存中
        User user3 = (User) session.load(User.class, 2);
        //将user3从session缓存中移除
        System.out.println(user3.getEmail() + "   user3");
        //测试user4也就是user2是否从二级缓存中移除
        User user4 = (User) session.load(User.class, 3);
        System.out.println(user4.getEmail() + "user4");
        
        session.close();
    }


测试结果:二级缓存期间更新失败

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
==============================
Hibernate:
    select
        user0_.id as id112_0_,
        user0_.email as email112_0_,
        user0_.nickname as nickname112_0_,
        user0_.password as password112_0_,
        user0_.user_integral as user5_112_0_,
        user0_.is_email_verify as is6_112_0_,
        user0_.email_verify_code as email7_112_0_,
        user0_.last_login_time as last8_112_0_,
        user0_.last_login_ip as last9_112_0_
    from
        dangdang.d_user user0_
    where
        user0_.id=?
chenhaixin2163@163.com
Hibernate:
    select
        user0_.id as id112_0_,
        user0_.email as email112_0_,
        user0_.nickname as nickname112_0_,
        user0_.password as password112_0_,
        user0_.user_integral as user5_112_0_,
        user0_.is_email_verify as is6_112_0_,
        user0_.email_verify_code as email7_112_0_,
        user0_.last_login_time as last8_112_0_,
        user0_.last_login_ip as last9_112_0_
    from
        dangdang.d_user user0_
    where
        user0_.id=?
ddddd:::::ddadddd
++++++++++++++








资料整理:

1:在read-write模式下:
我们有一个Order对象,是一个实体对象,对应数据库中order表中的一条记录,经过查询已有n个Order对象被放入二级缓存中。现在我们要修改order表中任意任x条记录,执行以下HQL:

template.bulkUpdate("update Order set owner = ? where id in (?,?,?)");

 

 这时Hibernate会直接将二级缓存中的n个Order对象清除掉。 天啊,居然不是你想像的修改谁就同步更新二级缓存中的谁,而是清除了二级缓存中全部的Order类型的对象。为什么?这一切是为了保证“数据一致性”。你执行了HQL修改了order表中的x条记录,这x条是哪几条?如果sql是子查询:update Order set owner =? where id in(select id from *** ),谁知道你修改了order表中的哪几条记录,你自己都不知道,Hibernate更不知道了。所以为了保证二级缓存中的数据与order表中的数据一致,只能清除了二级缓存中全部的Order类型的对象。二级缓存频繁的载入与清除,这样缓存命中率就会下降。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值