Hibernate框架--对象的状态,缓存, 映射

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate框架--对象的状态,缓存, 映射相关的知识,希望对你有一定的参考价值。

回顾Hibernate第二天:

1.  一对多与多对一

2. 多对多

3. inverse/cascade

4. 关联关系的维护

 

一对多:

         <set name="映射的集合属性" table="(可选)集合属性对应的外键表">

            <key column="外键表的,外键字段" />

            <one-to-many class="集合元素的类型" />

         </set>

 

多对一:

    <many-to-one name="对象属性" class="对象类型" column="外键字段字段" />

 

多对多

    <set name="" table="">

        <key column="" />

        <many-to-many column="" class="">

    </set>

 

目标:

         第1部分: 对象的状态:

         第2部分:缓存

                   1) 一级缓存

                   2) 相关知识

         ----懒加载---

         第3部分:映射

                   一对一映射

                   组件映射

                   继承映射

 

一、对象的状态

举例: User   user   = new User();

 

Hibernate中对象的状态: 临时/瞬时状态、持久化状态、游离状态。

1. 临时状态

  特点:

  直接new出来的对象; 

  不处于session的管理;

  数据库中没有对象的记录;

1. 持久化状态

  当调用session的save/saveOrUpdate/get/load/list等方法的时候,对象就是持久化状态。

  处于持久化状态的对象,当对对象属性进行更改的时候,会反映到数据库中!

  特点:

  处于session的管理;

  数据库中有对应的记录;

3. 游离状态

  特点:

          不处于session的管理;

          数据库中有对应的记录

          Session关闭后,对象的状态;

对象状态的转换 

 

public class User {

    private int userId;
    private String userName;
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    @Override
    public String toString() {
        return "User [userId=" + userId + ", userName=" + userName + "]";
    }
    
    
}

 

<hibernate-mapping package="cn.itcast.a_status">
    
    <class name="User" table="t_user">
        <id name="userId" column="id">
            <generator class="native"></generator>
        </id>    
        <property name="userName"></property>
    </class>
    

</hibernate-mapping>
public class App1_status {
    
    private static SessionFactory sf;
    static {
        sf = new Configuration()
            .configure()
            .addClass(User.class)   // 测试时候使用
            .buildSessionFactory();
    }

    //1. 对象状态的转换
    @Test
    public void testSaveSet() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        
        // 创建对象                        【临时状态】
//        User user = new User();
//        user.setUserName("Jack22222");
        // 保存                            【持久化状态】
//        session.save(user);        
//        user.setUserName("Jack333333");  // 会反映到数据库
        
        
        // 查询
        User user = (User) session.get(User.class, 5);
        user.setUserName("Tomcat");// hibernate会自动与数据库匹配(一级缓存),如果一样就更新数据库
        
        session.getTransaction().commit();
        session.close();
        
        
        user.setUserName("Jack444444444");
        // 打印                            【游离状态】
        System.out.println(user.getUserId());
        System.out.println(user.getUserName());
    }
    
    
    @Test
    public void bak() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        session.getTransaction().commit();
        session.close();
    }
}

 

二、一级缓存

为什么要用缓存?

         目的:减少对数据库的访问次数!从而提升hibernate的执行效率!

Hibernate中缓存分类:

         一级缓存

         二级缓存

 

ü  概念

1)Hibenate中一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数!  只在session范围有效! Session关闭,一级缓存失效!

2)当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session的缓存中。

3Session的缓存由hibernate维护, 用户不能操作缓存内容; 如果想操作缓存内容,必须通过hibernate提供的evit/clear方法操作。

特点:

         只在(当前)session范围有效,作用时间短,效果不是特别明显!

         在短时间内多次操作数据库,效果比较明显!

 

 

ü  缓存相关几个方法的作用

    session.flush();       让一级缓存与数据库同步

           session.evict(arg0);    清空一级缓存中指定的对象

           session.clear();       清空一级缓存中缓存的所有对象

 

在什么情况用上面方法?

           批量操作使用使用:

                    Session.flush();   // 先与数据库同步

                    Session.clear();   // 再清空一级缓存内容

                          

ü  面试题1: 不同的session是否会共享缓存数据?  不会。

User1  u1 = Session1.get(User.class,1);   把u1对象放入session1的缓存

Session2.update(u1);     把u1放入session2的缓存

 

U1.setName(‘new Name’);

 

如果生成2条update sql, 说明不同的session使用不同的缓存区,不能共享。

 

ü  面试题2: list与iterator查询的区别?

list()

一次把所有的记录都查询出来,

会放入缓存,但不会从缓存中获取数据

         Iterator

                   N+1查询; N表示所有的记录总数

                   即会先发送一条语句查询所有记录的主键(1),

再根据每一个主键再去数据库查询(N)!

会放入缓存,也会从缓存中取数据!

 

public class App2_cache {
    
    private static SessionFactory sf;
    static {
        sf = new Configuration()
            .configure()
            .addClass(User.class)   // 测试时候使用
            .buildSessionFactory();
    }

    @Test
    public void testCache() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        User user = null;
        // 查询
        user = (User) session.get(User.class, 5);// 先检查缓存中是否有数据,如果有不查询数据库,直接从缓存中获取
        user = (User) session.get(User.class, 5);// 这一句就不再向数据库发送查询命令了,减少了与数据库的交互。
        
        session.getTransaction().commit();
        session.close();
    }
    
    
    
    @Test
    public void flush() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        
        User user = null;
        user = (User) session.get(User.class, 5);
        user.setUserName("Jack");
        // 缓存数据与数据库同步
        session.flush();
        
        user.setUserName("Jack_new");
        
        session.getTransaction().commit();  // session.flush();
        session.close();
    }
    
    @Test
    public void clear() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        
        User user = null;
        // 查询
        user = (User) session.get(User.class, 5);
        // 清空缓存内容 
//        session.clear(); // 清空所有
        session.evict(user);// 清除指定
        
        user = (User) session.get(User.class, 5);
        
        
        session.getTransaction().commit();  // session.flush();
        session.close();
    }
    
    @Test
    public void sessionTest() throws Exception {
        Session session1 = sf.openSession();
        session1.beginTransaction();
        Session session2 = sf.openSession();
        session2.beginTransaction();
        
        // user放入session1的缓存区
        User user = (User) session1.get(User.class, 1);
        // user放入session2的缓存区
        session2.update(user);
        
        // 修改对象
        user.setUserName("New Name");  // 2条update
        
        
        
        session1.getTransaction().commit();  // session1.flush();
        session1.close();
        session2.getTransaction().commit();  // session2.flush();
        session2.close();
    }
}

 

以上是关于Hibernate框架--对象的状态,缓存, 映射的主要内容,如果未能解决你的问题,请参考以下文章

Java实战之02Hibernate-02映射一级缓存实体对象状态

Hibernate缓存组件继承映射

Hibernate性能优化之EHCache缓存

hibernate笔记

Java三大框架之——Hibernate中的三种数据持久状态和缓存机制

Hibernate框架第三天