第二章:hibernate 入门
本章内容:
1)Hibernate核心接口的简介
2)Hibernate的各个元素组成
3)开发Hibernate的基本步骤
4)通过Hibernate ApI编写访问数据库
5)访问Session接口的方法
6)管理SessionFactory,Session对像
7)Session与事务的关系
Hibernate核心接口的简介
hibernate是java应用程序和关系数据库之间的桥梁,它负责java对像和关系数据库之间的映射。
hibernate内部封装了大量的通过jdbc访问数据库的操作。所以在hibernate开发文档中说hibernate是 对jdbc的轻量级封装。而hibernate向业务层提供了面向对像的数据库访问接口,使我们能够用面向对 像的途径去操作关系型数据库。基本上hibernate的核心可以分成几类:
1)提供访问数据库操作的接口(保存,更新,删除,查询对像)的接口。这些接口包括:
Session,Transaction,Query接口
2)用于配置hibernate的接口:Configuration
3)回调接口:使用应用程序接受Hibernate内部发生的事件:Interceptor,Lifecycle
4)用于扩展hibernate的功能的接口:UserType等.
5)我们平常用得最多的就是前2个接口
6)所有的hibernate应用中都会访问到hibernate的五个核心接口:
A:Configuration接口:负责读取hibernate配置文件,从而创建SessionFactory对像
B:SessionFactory接口:负责创建Session对像
C:Session接口:负责保存,更新,删除,加载和查询对像。(与jsp中的session不一样)
D:Transaction:管理事务
E:Query和Criteria:执行数据库查询
7)SessionFactory:它是重量级的,这意味着不能随意创建或销毁它的实例。如果应用只访问
一个数据库,只需要创建一人SessionFactory实例。并且该实例一般是在Web应用程序初始
化访问该实例。这所以称SessionFactory是重量级的,是因为它需要一个很大的缓存用来存
放序定义的sql语句。
8)Session接口是hibernate应用程序中使用最广泛的接口。Session也被称为持久化管理器。
Session实例是轻量级的。所以它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常
创建或销毁Session对像。
Hibernate的各个元素组成
1:POJO(Plain Old Java Object)你可以把它看作是简单的JavaBean.一般说来一张数据库表对应一个 POJO也就是对象/关系的一一映射。
2:DAO:对于每一个POJO,一般都有一个DAO与之对应,承担所有关于该POJO的访问控制。实际上也就是控制 了对数据库中一张表的访问控制。对表实现最基本的操作。增,删,改,查
3:*.hbm.xml文件:这个文件定义了POJO和数据库中的表是如何映射的,比如POJO中的字段对应数据库表中 的哪个字段等等。一般每个映射都用单独的文件来描述,也就是有一个POJO就有一个*.hbm.xml文件
4:Hibernate.cfg.xml文件:这个文件定义了Hibernate的基本信息,比如数据库驱动,用户名,密码等等连 接信息也包括了所有要用的*.hbm.xml文件,在初始化的时候,Hibernate会读取这个文件来找相应 的映射文件完成对象/关系
开发Hibernate的基本步骤
1)创建Hibernate的配置文件。
Hibernate配置文件用来指定Hibernate将与那个数据源进行连接。Hibernate配置文件名一般是 Hibernate.cfg.xml来命名的.值得注意的是这个Hibernate.cfg.xml配置文件不在WEB-INF下面而 在WEB-INF\classes下面。与struts-config.xml不同
A:先创建一个数据源驱动
1:window-->preferences-->MyEclipse-->database explorer-->database drivers-->
db Browser(右边)
2:注意在添加oracle数据库,不要选择classes12.jar。要添加ojdbc14.jar
B:选中工程-->Myeclipse-->addHibernate cablit..
C:在创建Hibernate.cfg.xml配置文件时,需要指定刚才创建的数据源
D:在添加addHibernate cablit的过程中要指定所显示的数据库架构scheam,一定要从数据源中
选择一个scheam。具体就是登录的用户名
E:在配置Hibernate.cfg.xml时会"自动"产生一个dialect属性用来指定被访问数据库所使用sql 方言.尽管关系数据库都支持sql语言,但是它们往往还有各自的sql方言,就像不同地区的
人既能说标准的普通话,还能讲各自的方言一样。这些方言是hibernate里面自动配置好了我
们只需要使用就行了
Oracle数据库的方言为:oracle 9/10g。sqlserver数据库的方言:Micrsoft sql server
2)创建持久化类(pojo类)。只包括get..set方法的描述类,也就是实体域类
3)创建对像-关系映射文件。
1:Hibernate采用xml格式的文件来指定对像和关系数据之间的映射。对像-关系映射文件里面指定了 持久化类与数据表之间的关系,同时也指定了持久化类中的属性与表中字段的关系。以后在运行时 Hibernate将根据这个映射文件来生成各种sql语句
2:每一个表必须有一个对像-关系映射文件,并且该映射文件的名字一般为:表名.hbm.xml
3:创建持久化类与创建对像-关系映射文件都可以通过Myeclipse自动生成,并且持久化类一定
要与其对应的映射文件在同一个文件夹下面
4)通过MyEclipse自动产生pojo类与对像-关系映射(mapping)文件
1)打开DB Browser-->选中要产生pojo类的表-->单右-->Hibernate reverser engineeing..
2)在之后和向导中勾选:Hibernate mapping file(*.xml) for..与java data object(pojo)
3)可以在DB Browser中一次性选择多个表。MyEclipse会同时生成多个表的pojo类与映射文件
4)在向导中我们会选择表中主键的生成方式。一般选择"assigned"
5)通过Hibernate ApI编写访问数据库的代码
访问Session接口的方法
1)save:把java对像保存到数据库中
2)update:更新数据库的java对像
3)delete:把java对像从数据库中删除
4)get:从数据库中根据OId加载java对像
5)find:方法从数据库查询java对像
通过Hibernate ApI编写访问数据库
1)通过Hibernate API访问数据库的步骤如下:
A:创建一个Configuration对像(导入对应的包:org.hibernate.cfg.Configuration)
Configuration cfg=new Configuration();
B:加载hibernate的配置文件
cfg.configure("/hibernate.cfg.xml");或
cfg.configure()这是一种默认加载方式。它会自动的加载hibernate.cfg.xml这个配置文件
但是如果文件名不是"hibernate.cfg.xml"比如:"chen.cfg.xml"则只能用第一种加载方法
C:通过Configuration对像创建一个SessionFactory(包:org.hibernate.SessionFactory)
SessionFactory sessionFactory=cfg.buildSessionFactory();
D:通过SessionFactory对像创建一个Session对像。(包:org.hibernate.Sessionw)
Session session=this.sessionFactory.openSession();
E:通过Session的各种方法进行对数据库的操作
public class deptDao
{
private static SessionFactory sessionFactory=null;
static
{
Configuration cfg=new Configuration();
cfg.configure();
sessionFactory=cfg.buildSessionFactory();
}
public static Dept get(int id) //通过id获取对应的一个dept的实例
{
Session session=sessionFactory.openSession();
Dept deptInstance=(Dept)session.get(Dept.class, new Long(id));
//一定要注意这里面不能写成
Dept deptInstance=(Dept)session.get(Dept.class,id);
session.close();
return deptInstance;
}
public static void save(Dept deptInstance) //执行添加功能
{
Session session=sessionFactory.openSession();
Transaction tran=session.beginTransaction();
session.save(deptInstance);
tran.commit();
session.close();
}
public static void update(Dept deptInstance) //执行修改功能
{
Session session=sessionFactory.openSession();
Transaction tran=session.beginTransaction();
session.update(deptInstance);
tran.commit();
session.close();
}
public static void del(Dept deptInstance) //执行删除功能,根据对像删除
{
Session session=sessionFactory.openSession();
Transaction tran=session.beginTransaction();
session.delete(deptInstance);
tran.commit();
session.close();
}
public static void del(int id) //执行编号执行删除功能
{
Session session=sessionFactory.openSession();
Transaction tran=session.beginTransaction();
session.delete(get(id));
tran.commit();
session.close();
}
public static List findByDeptLoc(String loc) //按部门位置查询
{
Session session=sessionFactory.openSession();
List deptList=session.createQuery("from Dept where loc='"+loc+"'" ).list();
session.close();
return deptList;
}
管理SessionFactory,Session
1)Session接口是Hibernate应用中使用最广泛的接口。Session也被称为持久化管理器,它提供 了和持久化相关的操作.如:添加,更新,删除,加载和查询对像
2)Session不是线程安全的,因此应尽量避免多个线程共享同一个Session实例,也就是说每一个
连接必须有属于自己的Session
3)Session实例是轻量级的.所谓轻量级,是指它的创建和销毁不需要太多的资源.这意味着程序 中可以经常创建或销毁Session对像.一般都是为每一个客户请求分配一个Session实例.然后 把Session与事务绑定在一起.开始执行事务时打开,事务执行完毕之后关闭.Session不是线程
安全的,也就是说多个线程不能同时访问Session。
4)那么如何能够保证为每一个客户端都会有属于自己的Session呢?我们可以通过一个java中的 一个类ThreadLocal(线程局部变量类,不是本地线程).这个类能够为每一个客户端的线程都创 建一个属于本客户端的变量.
5)SessionFactory是重量级对像.它是线程安全的,也就是所有客户端可以共享一个 SessionFactory,而且不能经常创建与销毁,所以可以做成为单例模式
5)一般的格式:
该类使用了饿汉单例模式,并把SessionFactory封装在类里面。只留一个Session接口
public class SessionManager
{
//只有静态变量才能做为单例模式
private static SessionFactory sessionFactory=null;
private static ThreadLocal threadLocal=null;
private static SessionManager sessionManager=null; //饿汉单例模式
static //静态变量初始器,该初始器只会在类加载时执行一次
{
Configuration cfg=new Configuration();//创建一个Configuration实例
cfg.configure();//加载hibernate.cfg.xml文件
sessionFactory=cfg.buildSessionFactory();
threadLocal=new ThreadLocal();
sessionManager=new SessionManager();
}
public void closeSession() //关闭session
{
Session session=(Session)threadLocal.get();//从线程局部变量中获取session
if (session!=null)
{
session.close();
}
threadLocal.set(null);//删除线程局变量中的session,释放资源
}
public static SessionManager newInstance() //饿汉单例模式
{
return sessionManager;
}
public Session getSession()
{
Session session=(Session)threadLocal.get();//从线程局部变量中获取session
if (session==null)
{
session =sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
}
6)使用基于SessionManager的dao数据层做成如下的形式:
//注意如果有方法之间相互调用的情况考虑session多次关闭的情况
public class DeptDao
{
public static Dept get(int id) //通过id获取对应的一个dept的实例
{
Session session=SessionManager.newInstance().getSession();
Dept deptInstance=(Dept)session.get(Dept.class, new Long(id));
SessionManager.newInstance().closeSession();
return deptInstance;
}
public static void save(Dept deptInstance) //执行添加功能
{
Session session=SessionManager.newInstance().getSession();
Transaction tran=session.beginTransaction();
session.save(deptInstance);
tran.commit();
SessionManager.newInstance().closeSession();
}
public static void update(Dept deptInstance) //执行修改功能
{
Session session=SessionManager.newInstance().getSession();
Transaction tran=session.beginTransaction();
session.update(deptInstance);
tran.commit();
SessionManager.newInstance().closeSession();
}
public static void del(Dept deptInstance) //执行删除功能,根据对像删除
{
Session session=SessionManager.newInstance().getSession();
Transaction tran=session.beginTransaction();
session.delete(deptInstance);
tran.commit();
SessionManager.newInstance().closeSession();
}
public static void del(int id) //执行编号执行删除功能
{
Session session=SessionManager.newInstance().getSession();
Transaction tran=session.beginTransaction();
session.delete(get(id));
//这里在调用本类中的get方法,会出现错误,因为
//get方法已经关闭了session对像,导致下面的操作无法进行
tran.commit();
SessionManager.newInstance().closeSession();
}
public static List findByDeptLoc(String loc) //按部门位置查询
{
Session session=SessionManager.newInstance().getSession();
List deptList=session.createQuery("from Dept where loc='"+loc+"'" ).list();
SessionManager.newInstance().closeSession();
return deptList;
}
}
Session与事务的关系
1)hibernate规定每一个对pojo对像的持久化操作必须要与对应的事务联系到一起
2)当要执行一个事务时,Session会打开
3)事务执行完毕之后,为了释放对应资源,Session要关闭
4)但是在执行事务的过程中可能会发生异常。所以要对pojo持久化操作进行事务处理
6)事务只是对应于Pojo持久化对像的改变。pojo对像没有改变,则不用加事务.所以
事务一般是是针对于。增,删,改。这些操作而言,对于查没由于不存在数据的修改
所以可以不用事务
5)一般的格式是:
Session session=SessionManager.newInstance().getSession();
Transaction tran=session.beginTransaction();
try
{
session.save(deptInstance);
tran.commit();
}catch(Exception e)
{
tran.rollback();
}
finally
{
SessionManager.newInstance().closeSession();
}
评论