Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载Java 对象的方法.
配置hibernate.cfg.xml文件
测试session的产生方式
package cn.itcast.hibernate0909.session;
import java.lang.annotation.Target;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import cn.itcast.hibernate0909.onetomany.doubl.Classes;
/**
* * hibernate中的crud操作是利用session来完成的
* * hibernate中的事务是依赖于session环境的
* * session的产生的方式
* * sessionFactory.openSession
* 每次都会新创建一个session,只要新创建一个session,hibernate都会打开应用程序和数据库的连接
* 所以这种方式效率比较低
* * sessionFactory.getCurrentSession
* * 如果当前线程中没有session,先openSession,然后把session存放到当前线程中
* * 从当前线程中得到session
* * crud操作必须有事务环境
* * 不用手动去close掉
* * session的一级缓存
* @author Administrator
*
*/
public class SessionTest {
private static SessionFactory sessionFactory;
static{
Configuration configuration = new Configuration();
//加载配置文件
configuration.configure("cn/itcast/hibernate0909/session/hibernate.cfg.xml");
//采用了工厂模式创建sessionFactory
sessionFactory = configuration.buildSessionFactory();
}
private void testSession(String name){
Session session = sessionFactory.getCurrentSession();
//Transaction transaction = session.beginTransaction();
Classes classes = (Classes)session.get(Classes.class, 1L);
//classes.setCname(name);
//transaction.commit();
//session.close();
}
@Test
public void test(){
SessionTest sessionTest = new SessionTest();
sessionTest.testSession("aaa");
}
}
junit测试结果
* * hibernate中的crud操作是利用session来完成的
* * hibernate中的事务是依赖于session环境的
* * session的产生的方式
* * sessionFactory.openSession
* 每次都会新创建一个session,只要新创建一个session,hibernate都会打开应用程序和数据库的连接
* 所以这种方式效率比较低
* * sessionFactory.getCurrentSession
* * 如果当前线程中没有session,先openSession,然后把session存放到当前线程中
* * 从当前线程中得到session
* * crud操作必须有事务环境
* * 不用手动去close掉
* * session的一级缓存
junit测试结果:
可以看出只查询了一次数据库
junit测试结果:
可以看出并没有发出select语句去查询班级
junit测试结果:
可以看出第二次查询并没有发出select语句去查询班级
区别:
flush: 进行清理缓存(此时缓存中的数据并不丢失)的操作,让缓存和数据库同步 执行一些列sql语句,但不提交事务,;
commit:先调用flush() 方法,然后提交事务. 则意味着提交事务意味着对数据库操作永久保存下来。
reresh:刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本地缓存的对象状态.
clear:清空缓存,等价于list.removeAll();
junit测试结果:
junit测试结果:
session.flush方法
hibernate内部会去检查session缓存中的所有的对象
如果该对象是持久化对象,并且该对象的ID在数据库中有对应的记录,并且该对象的属性
有变化,则会自动发出update语句,如果该对象的属性没有变化,则不发出update语句
检查持久化对象中是否有关联的对象,如果有关联的对象,并且设置了级联操作,这个时候
会检查级联对象的id在数据库中有没有对应的记录,如果有,则发出update语句,如果没有,则
发出insert语句
如果有维护关系的代码,则还会改变关系
全部检查完成以后,就发出sql语句,把一级缓存中的内容同步到数据库中
junit测试结果:
1 Customer c = new Customer(“TOM”,new HashSet());
2 session.save(c); //customer对象被持久化,并且加入到session的缓存中
3 Long id = c.getId();
4 c = null; //c变量不再引用customer对象
5 //从session缓存中读取customer对象,使c2变量引用customer对象
6 Customer c2 = (Customer)session.load(Customer.class,id);
7 tx.commit(); //缓存中的对象和数据库同步
8 session.close(); //关闭session 清空缓存
9 System.out.println(c2.getName()); //访问customer对象
10 C2 = null; //C2对象不再引用customer对象,customer对象结束生命周期
缓存的作用:
1。减少访问数据库的频率。
2。保证缓存中的对象与数据库中的相关记录保持同步。
可以写一个for循环,Session可以批量插入上万条数据。如下面的代码:
For(int i=0;i<10000;i++){
Session.save(object);
}
这样写的代码会产生一个什么问题?会使一万个对象的缓存全部存在于内存中,这样做加大了内存的压力。所以应该定期清理session的缓存,也就是flush一下,这样内存才能保证足够的空间。
场合一:当用户要取数据库的一张表的一个字段,这个字段很可能就是一个字符,总而言之长度是比较短的。
场合二:当用户要取数据库的一张表的一个字段的值,而这个值很可能是blob类型,也许存取的是一个很大的视频文件。
两种场合的取数据的方法一样吗?是用load还是用get方法?
package cn.itcast.hibernate0909.session.cache;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import cn.itcast.hibernate0909.onetomany.doubl.Classes;
import cn.itcast.hibernate0909.onetomany.doubl.Student;
/**
* 1、一级缓存的生命周期
* 一级缓存在session中存放,只要打开session,一级缓存就存在了,当session关闭的时候,一级缓存就不存在了
* 2、一级缓存是依赖于谁存在的
* 依赖于session存在的
* 3、怎么样把数据存放到一级缓存中
* 利用session.get、update、save
* 4、怎么样从一级缓存中获取数据
* 利用session.get方法可以获取数据
* 5、怎么样把缓存中的数据同步到数据库
* * 只要是一个持久化状态的数据就在一级缓存中
* * 利用session.flush方法
* 6、怎么样把数据库的数据同步到一级缓存中
* session.reflesh方法 只能同步一个对象
* 7、一级缓存的特性
* 也叫session级别的缓存
* session中存放私有数据
* 可以通过新建session和从当前线程中获取session保证数据的安全性
* 8、从一级缓存中清楚某一个对象
* session.evcit方法 并且把一个对象从持久化状态转化成脱管状态
* 9、清空一级缓存中所有的数据
* @author Administrator
*
*/
public class OneCacheTest {
private static SessionFactory sessionFactory;
static{
Configuration configuration = new Configuration();
//加载配置文件
configuration.configure("cn/itcast/hibernate0909/session/hibernate.cfg.xml");
//采用了工厂模式创建sessionFactory
sessionFactory = configuration.buildSessionFactory();
}
/**
* session.get方法
* * 通过该方法得到的对象是一个持久化对象
* * 通过该方法可以把该对象存放到一级缓存中(session缓存中)
*/
@Test
public void testGet(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Classes classes = (Classes)session.get(Classes.class, 1L);
session.get(Classes.class, 1L);
transaction.commit();
}
/**
* session.save方法
* * 可以把一个对象变成持久化状态的对象
* * 可以把一个对象放入到一级缓存中
*/
@Test
public void testSave(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Classes classes = new Classes();
classes.setCname("重点班");
classes.setDescription("高材生");
session.save(classes);
Classes classes2 = (Classes)session.get(Classes.class, classes.getCid());
transaction.commit();
}
/**
* session.update方法
* * 能把一个对象的状态转化成持久化状态
* * 能把一个对象存放到一级缓存中
*/
@Test
public void testUpdate(){
/**
* 1、利用get方法获取
* 2、利用session.evict方法清空
* 3、再利用update方法
* 4、再用get方法获取
*/
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Classes classes = (Classes)session.get(Classes.class, 2L);
session.evict(classes);//用session.evict方法清空
classes.setDescription("aaa");
session.update(classes);
Classes classes2 = (Classes)session.get(Classes.class,2L);
transaction.commit();
}
@Test
public void testFlush(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
//持久化状态的数据
Classes classes = (Classes)session.get(Classes.class, 1L);
Set<Student> students = classes.getStudents();
for(Student student:students){
student.setClasses(null);
}
Student student = new Student();
student.setSname("菜肉哥!");
student.setDescription("厉害!!!!!");
Student student2 = new Student();
student2.setSname("包子哥!");
student2.setDescription("真厉害!!!!!");
// student.setClasses(classes);
// student2.setClasses(classes);
students.add(student);
students.add(student2);
/**
* session.flush方法
* * hibernate内部会去检查session缓存中的所有的对象
* * 如果该对象是持久化对象,并且该对象的ID在数据库中有对应的记录,并且该对象的属性
* 有变化,则会自动发出update语句,如果该对象的属性没有变化,则不发出update语句
* * 检查持久化对象中是否有关联的对象,如果有关联的对象,并且设置了级联操作,这个时候
* 会检查级联对象的id在数据库中有没有对应的记录,如果有,则发出update语句,如果没有,则
* 发出insert语句
* * 如果有维护关系的代码,则还会改变关系
* * 全部检查完成以后,就发出sql语句,把一级缓存中的内容同步到数据库中
*/
session.flush();
transaction.commit();
}
@Test
public void testFlush2(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Student student1 = (Student)session.get(Student.class, 1L);
Student student2 = (Student)session.get(Student.class, 2L);
student1.getClasses().setCname("aaa");
student2.getClasses().setDescription("asdf");
session.flush();
transaction.commit();
}
@Test
public void testReflesh(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Classes classes = (Classes)session.get(Classes.class, 1L);
classes.setCname("bbb");
//把一个对象对应的数据库的数据重新更新到一级缓存中
session.refresh(classes);
session.clear();//清空一级缓存中的所有的数据
classes = (Classes)session.get(Classes.class, 1L);
System.out.println(classes.getCname());
transaction.commit();
}
/**
* 批量操作
*/
@Test
public void testBatchSave(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
for(int i=0;i<100000;i++){
if(i%50==0){
session.flush();
session.clear();
}
Classes classes = new Classes();
classes.setCname(i+"aaa");
session.save(classes);
}
transaction.commit();
}
}
lazy 为true或者为false
断点debug运行发现在classes.getCname();发出sql语句
lazy 设置为false重新测试
断点debug运行发现在session.load(Classes.class, 1L);就发出了sql语句
True false extra
extra为更进一步的延迟加载策略。
当调用getStudents()时不会加载hql语句,当加载student的属性的时候才会发出SQL语句
调用getStudents().size()方法的时候,会触发类似于:Hibernate: select count(id) from T_Student where classid =? 这样的SQL查询语句(这是一种很聪明的做法,如果lazy=”true”,getStudents().size()将会使得hibernate加载所有集合的数据到内存中)。
调用getStudents().contains()方法的时候(即判断是否包含某个对象),会触发类似于:select 1 from T_Student where classid =? and id =? 这样的SQL查询语句。
lazy=”true”
断点debug运行
lazy=”false”
断点debug运行
lazy=“extra”
False proxy no-proxy
proxy:当前对象的単值相关对象只有在调用它的主键外的其他属性的get方法时才加载它。
no-proxy:当前对象的単值相关对象只有在调用它的属性时才加载,需要字节码增强。
package cn.itcast.hibernate0909.lazy;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
/**
* 懒加载
* 针对数据库中的大数据,不希望特别早的加载到内存中,当用到它的时候才加载
* 类的懒加载
* 集合的懒加载
* 单端关联的懒加载
* @author Administrator
*
*/
public class LazyTest {
private static SessionFactory sessionFactory;
static{
Configuration configuration = new Configuration();
//加载配置文件
configuration.configure("cn/itcast/hibernate0909/lazy/hibernate.cfg.xml");
//采用了工厂模式创建sessionFactory
sessionFactory = configuration.buildSessionFactory();
}
/**
* 类的懒加载
* * 在默认情况下,类就是执行懒加载
* * 只有使用了load方法以后才能用懒加载
* * 如果在相应的映射文件中,设置<class>的lazy="false"懒加载将失去效果
*/
@Test
public void testLoad(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Classes classes = (Classes)session.load(Classes.class, 1L);
String cname = classes.getCname();//发出sql语句
System.out.println(cname);
transaction.commit();
}
/**
* 集合的懒加载
* 针对一多对的情况或者多对多的情况
* 根据一方加载set集合,决定在什么时候给set集合填充数据
* true
* 在遍历集合中的每一个元素的时候发出sql语句
* false
* 在得到集合的时候,发出sql语句
* extra
* students.size()这个时候用extra仅仅能够得到大小
*/
@Test
public void testCollectionLazy(){
Session session = sessionFactory.openSession();
Classes classes = (Classes)session.load(Classes.class, 2L);
Set<Student> students = classes.getStudents();
System.out.println(students.size());
session.close();
}
/**
* 单端关联
* 根据多的一方加载一的一方
* false
* proxy 就相当于true
* no-proxy
* 根据多的一方加载一的一方数据量特别少,所以怎么样都行
*/
}
原文:http://blog.csdn.net/cckevincyh/article/details/54863991