美文网首页
2018-09-28:HibernateDML操作与缓存

2018-09-28:HibernateDML操作与缓存

作者: 神坛下的我 | 来源:发表于2018-09-28 16:43 被阅读0次

    Hibernate对象声明周期和DML

    • java对象在Hibernate中的生命周期指的是java类和数据库的关联状态。
    1. 临时状态(新建状态)
      新new出来的java类对象和对应的数据库表 数据上没有关联
    2. 持久化状态
      java类对象和对应的数据库表 数据上完全一致(同步)
    3. 托管状态
      java类对象和对应的数据库表 数据上曾经一致,现在脱离
    • save 总是发送insert语句,主键存在会主键冲突,主键不存在插入成功,只能
      从新建状态或持久化状态经过evict和clear编程托管状态开始。

    • merge 无论是新建状态还是evict后的托管状态,无论主键是否修改,因为总是
      先执行了select去查询数据库中是否已存在,该主键,不存在insert,存在update。

    • update 无论修改了任何内容,只要和原值不一样,都会发送update语句。

    • 为什么建表时有详情表和总量表:当数据量特别巨大,查询次数特别频繁,通过
      group by 等语句计算出总量特别浪费资源,宁愿每次数据变化同步修改总量表,
      而且反复查询一张表Hibernate可以开缓存(一级 二级)提高效率。

    TestDML.java

    
    Session session = HibernateSessionFactory.getSession();
    Transaction tran = session.beginTransaction();
    **********************************************************
    //1.新增 使用save方法save只认新建状态和持久化状态,新建状态是insert,
    持久化状态是update,托管状态由于会发送insert语句往往会主键冲突
    //连续对同一对象两次save,第二次如果有非主键字段修改,第一次发送insert
    语句,第二次发送update语句。第二次修改主键字段会报错。
    Teacher teacher = new Teacher("0011","zhangsan","London");//新建状态
    teacher.setTno("0012");
    session.save(teacher);//持久化状态
    **********************************************************
    //2.修改 通过get得到对象,该对象为持久化状态,但是如果clear evict对象
    变为托管状态,托管状态对象执行save发送insert语句往往因为主键冲突不成功。
    //不清理clear 对象为持久化状态,无论使用update还是merge如果修改值和原值
    一样都发送update语句,如果执行了clear,对象变为托管状态,虽然如果和原值
    不同最后都会执行update语句merge会再次查询后才update,update不会。
    Teacher teacher = session.get(Teacher.class,"0001");
    teacher.setSex("女");
    session.evict(teacher);
    session.clear();
    session.update(teacher);
    session.merge(teacher);
    //对于持久化状态的对象 修改主键后执行save和merge 都报错不准修改主键,
    如果持久化状态的对象被evict之后,修改了主键使用save无论修改的主键是否
    存在都发送insert;merge修改主键存在发送update,没有发送insert。
    Teacher teacher = session.get(Teacher.class,"0001");
    session.evict(teacher);
    teacher.setTno("0001");
    session.save(teacher);
    session.merge(teacher);
    //新建状态的对象 如果有主键已存在 执行save报错重复的主键和merge
    ********************************************************
    //3.删除(持久化状态情况下)
    Teacher teacher = session.get(Teacher.class,"0002");
    session.delete(teacher);
    
    tran.commit();
    HibernateSessionFactory.closeSession();
    
    
    

    缓存

    1. 如果开启了查询缓存,不清理session情况下,在两个事务中第二次查询同一
      数据不发送sql,清理缓存(session.clear()) 后则会发送sql。
    2. 如果开启了二级缓存,无论清不清理session,两次查询都只发送一次sql
      配置hibernate二级缓存:ehcache-core.jar包中找到ehcache-....xml
      文件复制到src目录下(其中改动path和maxElementsInMemory="10"<-修改数据
      大小是查询出的数据最多多少条放内存中缓存,多出的放在指定缓存文件夹)。
      由于二级缓存存放多条数据,需要使用list,iterator这样的集合查询
      ,才会使用二级缓存并且在执行代码需要 query.setCacheable(true)
    3. Iterator执行查询是N+1方式,数据库中有n条记录,先1条查询出主键集合,
      再依次按照需要具体访问的值得主键进行查询。

    TestCache.java

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import gxa.dao.HibernateSessionFactory;
    import gxa.entity.Student;
    
    public class TestCache {
        public static void main(String[] args) {
            // 实验一 在两个事务分别进行两次 同一学生的查询,如果清理session 两次 两条,不清理两次一条
            // 实验二 如果开启了二级缓存,配置二级缓存的设置和工厂类的设置
            Session session = HibernateSessionFactory.getSession();
            // Transaction tran1 = session.beginTransaction();
            // Student student1 = session.load(Student.class, "09010101");
            //
            // System.out.println(student1.getName());
            // session.clear();// 在 关闭二级缓存后生效
            // tran1.commit();
            //
            // Session session2 = HibernateSessionFactory.getSession();
            // Transaction tran2 = session2.beginTransaction();
            // Student student2 = session2.load(Student.class, "09010101");
            // System.out.println(student2.getName());
            // //session2.clear();
            // tran2.commit();
    
            // 实验三 ,两次查询多条记录,开启二级缓存设置使用缓存为true 两次查询发送1条,否则都是发两条
            // Transaction tran1 = session.beginTransaction();
            // Query query = session.createQuery("From Student");
            // //query.setCacheable(true);
            // List<Student> Students1 = query.list();
            // for (Student Student1 : Students1) {
            // System.out.println(Student1.getName());
            // }
            //
            // tran1.commit();
            //
            // Transaction tran2 = session.beginTransaction();
            // Query query2 = session.createQuery("From Student");
            // //query.setCacheable(true);
            // List<Student> Students2 = query.list();
            // for (Student Student2 : Students2) {
            // System.out.println(Student2.getName());
            // }
    
            // 实验四 iterator 执行查询是 n+1 方式,数据库中有n条记录,先1条查询查处主键集合,再依次按照需要具体访问的值的主键进行查询,
            //所有n条记录的主键,对应n条查询 
    
            Transaction tran4 = session.beginTransaction();
            Query query4 = session.createQuery("From Student");
            query4.setCacheable(true);
            Iterator<Student> students = query4.iterate();
            while(students.hasNext()){
                Student student = students.next();
                System.out.println(student.getName());
            }
            
            tran4.commit();
            
            Transaction tran5 = session.beginTransaction();
            Query query5 = session.createQuery("From Student");
            query4.setCacheable(true);
            Iterator<Student> students5 = query5.iterate();
            while(students5.hasNext()){
                Student student = students5.next();
                System.out.println(student.getName());
            }
            
            tran5.commit();
            session.close();
            System.exit(0);
        }
    }
    
    

    Student.java

    @Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
    public class Student implements java.io.Serializable {
    

    ehcache.xml

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    
        <diskStore path="d:/ehcache"/>
    
        <defaultCache
                maxElementsInMemory="13"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="true"
                maxElementsOnDisk="10000000"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU"
                />
    </ehcache>
    
    

    hibernate.cfg.xml

      <property name="hibernate.cache.use_query_cache">true</property>
      <property name="hibernate.cache.use_second_level_cache">true</property>
      
      
      
      <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
      <property name="show_sql">true</property>
      <mapping class="gxa.entity.Student"/>
      <mapping class="gxa.entity.Studentreg"/>
      <class-cache usage="read-only" class="gxa.entity.Student"/>
    

    集合

    • Set 无序集合,不认重复值
    • List 有序集合,知道初始大小
    • Iterator 有序的链式集合,不知道初始大小

    相关文章

      网友评论

          本文标题:2018-09-28:HibernateDML操作与缓存

          本文链接:https://www.haomeiwen.com/subject/lkmpoftx.html