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

2018-09-28  本文已影响0人  神坛下的我

Hibernate对象声明周期和DML

  1. 临时状态(新建状态)
    新new出来的java类对象和对应的数据库表 数据上没有关联
  2. 持久化状态
    java类对象和对应的数据库表 数据上完全一致(同步)
  3. 托管状态
    java类对象和对应的数据库表 数据上曾经一致,现在脱离

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"/>

集合

上一篇 下一篇

猜你喜欢

热点阅读