第二章: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(); }

评论