三、hibernate常用对象

 

一、自动创建表

我们可以在hibernate.cfg.xml上配备属性,让hibernate给我们自动创建表。

<!-- 自动生成表,加载hibernate.cfg.xml文件时,就会根据hbm文件在数据库中创建表,如果已经有此表就删除再创建-->

<property name="hbm2ddl.auto">create</property>
<!-- 加载hibernate.cfg.xml文件时,就会根据hbm文件在数据库中更新表(如果没表先创建表),即如果hbm文件中有尚未映射过的字段,就往数据库表中再新增此字段,不会删除原有字段-->

<property name="hbm2ddl.auto">update</property>
<!-- 加载hibernate.cfg.xml文件时,就会根据hbm文件在数据库中创建表,在显式关闭sessionFactory时,就drop掉此表-->

<property name="hbm2ddl.auto">create-drop</property>
<!-- 每次插入数据之前都会验证数据库中的表结构和hbm文件中是否一致-->

<property name="hbm2ddl.auto">validate</property>

在开发测试中,配置哪个都可以,但一般生成完数据库就会立即取消此配置。

二、事务回滚

如果在事务中有异常,我们是希望数据能够回滚的(不改变)

public static void updateEmployee() {

//1.获取一个对话

Session session=MySessionFactory.getSessionFactory().openSession();

//2.创建事务

Transaction ts=null;

 

try {

ts=session.beginTransaction();

//3.获取要修改的用户,load方法是通过主键属性获取该对象实例

Employee emp=(Employee) session.load(Employee.class, 1);

//4.修改信息

emp.setName("小小名");

 

//5.抛出异常

int i=9/0;

 

//6提交事务.

ts.commit();

} catch (Exception e) {

// TODO: handle exception

if(ts!=null){

ts.rollback();//事务回滚

}

//抛出一个运行时异常

throw new RuntimeException(e.getMessage());

}finally{

//7.关闭会话

if(session!=null&&session.isOpen()){

session.close();

}

}

 

}

三、configuration和配置文件

如果把hibernate.cfg.xml移到某个包下,并且更换了名字,就应该这样读取:

Configuration configuration=

new Configuration().configure("com/myz/config/hibernate.myz.xml");

可使用hibernate.properties文件来替代hibernate.cfg.xml文件(不建议)

 

四、SessionFactory(会话工厂)接口

①缓存sql语句和某些数据

②在应用程序初始化的时候创建,是一个重量级的类(吃内存),一般用单例模式保证一个应用只需要一个SessionFactory实例。

③如果某个应用访问多个数据库,则需要创建多个会话工厂实例。

④通过SessionFactory接口可以获得Session(会话)实例。

 

 

五、Session(会话)接口

Session一个实例代表与数据库的一次操作(当然一次操作可以是crud的组合)

session是线程不同步的(不安全),因此要保证在同一线程中使用,可以用getCurrentSession

Session可以看作是持久化管理器,它是与持久化操作相关的接口。

④openSession与getCurrentSession

Session session=sessionFactory.openSession();//获取一个全新的session

 

Session session=sessionFactory.getCurrentSession();//获取和当前线程绑定的session,在同一个线程中,我们获取的session是同一个session,这样利于事务控制。但是使用getCurrentSession需要在hibernate.cfg.xml下配置:

<!-- 能够使用getCurrentSession -->

<property name="current_session_context_class">thread</property>

openSession与getCurrentSession还有如下区别:

1.getCurrentSession创建的session会绑定到当前的线程中,而采用openSession创建的session则不会。

2.getCurrentSession创建的sessioncommitrollback时会自动关闭,而采用openSession创建的session必须手动关闭

3.getCurrentSession必须做成事务(查询也必须做成事务提交)

4.getCurrentSession需要在hibernate.cfg.xml文件中加入配置:

<!-- 与线程绑定,如果使用的是本地事务(jdbc事务) -->

property name="current_session_context_class">thread</property>

<!-- 如果使用的是全局事务(跨数据库的事务) -->

property name="current_session_context_class">jta</property>

 5.

SessionFactory启动的时候,hibernate会根据配置创建相应的CurrentSessionContext,在getCurrentSession被调用的时候,实际被执行的是:

CurrentSessionContex.currentSession()。在currentSession()执行时,如果当前session为空,currentSession会调用SessionFactoryopenSession

Session接口的几个重要方法

Session一般以对象的形式来操作,这是几个重要方法

1.保存一个对象(记录)--save方法

2.删除一个对象(记录)--delete方法

3.查询一个对象(记录)--get/load方法

4.修改一个对象(记录)--update方法

Get()Load()的区别

Get()方法直接返回实体类,如果查不到则返回nullload()会返回一个实体代理对象(当前这个对象可以自动转化为实体对象),但当代理对象被调用时,如果数据不存在,则会抛出异常

Load先到缓存(session缓存/二级缓存)中去查,如果没有则返回一个代理对象(不马上到DB中去找,即不发出sql语句),等后面使用这个代理对象操作的时候,才到DB中查询(发出SQL语句),这就是我们常说的load在默认情况下支持延迟加载(lazy)

Get先到缓存(session/二级缓存)中去查,如果没有就到DB中去查(立即发出SQL语句)。总之,如果你确定DB中有这个对象就用load(),不确定就用get()。这样效率高。

举例(查询一个不存在的记录)

Employee emp=(Employee) session.get(Employee.class, 8);

//发出了SQL语句

 

Employee emp=(Employee) session.load(Employee.class, 8);

//没发出SQL语句,没抛出异常

 

Employee emp=(Employee) session.get(Employee.class, 8);

System.out.println(emp);

//发出了SQL语句,并打出null

 

Employee emp=(Employee) session.load(Employee.class, 8);

System.out.println(emp);

//发出了SQL语句,之后抛出运行时异常

从上面我们可以看出,load方法是比较懒一些的,我们不使用查询到的对象时,它便不发出SQL语句去查询到底是否有这个对象。

这是因为load在默认情况下是支持延迟懒加载的(lazy),我们可以在Employee.hbm.xml中关闭延迟加载。

<class name="Employee" table="employee" lazy="false">

此时load方法,查询时也会立即发出SQL语句到数据库中查询。

 
Employee emp=(Employee) session.get(Employee.class, 8);

//发出了SQL语句,之后抛出了异常

六、缓存机制详解

注意:二级缓存需配置使用,否则仅有一级缓存。

Load方法查询:先到session缓存里查,如果没有则去二级缓存里查。如果二级缓存还没有查到,则不再往下查,返回一个代理对象。如果之后需要用到查询得到的对象,则直接发出sql语句去数据库里查,并将查询得到的对象存入二级缓存(根据查询次数的增多可能会被移动到一级缓存)

举例:

Employee emp=(Employee) session.load(Employee.class, 1);

System.out.println(emp.getName());

Employee emp2=(Employee) session.load(Employee.class, 1);

System.out.println(emp2.getHireDate());

//以上两句查询语句,仅产生了一条SQL语句,因为第二次是从二级缓存中取得的

Get方法查询:先到session缓存里查,如果没有则去二级缓存里查。如果二级缓存还查不到则立即发出SQL语句到数据库查询,并将查询得到的对象存入二级缓存(根据查询次数的增多可能会被移动到一级缓存)

举例:

Employee emp=(Employee) session.load(Employee.class, 1);

System.out.println(emp.getName());

Employee emp3=(Employee) session.get(Employee.class, 1);

System.out.println(emp3.getName());

//以上两句查询语句仅产生了一条SQL语句
原文地址:https://www.cnblogs.com/myz666/p/8423572.html