java---Hibernate

1 hibernate核心类和接口


 Configuraion类

         ①负责管理hibernate的配置信息

         ②读取hibernate.cfg.xml

         ③加载hibernate.cfg.xml配置文件中

配置的驱动,url,用户名,密码,连接池.

         ④管理 *.hbm.xml对象关系文件.

 

         示意代码:

         Configurationcf=new Configuration().configure();

         该类的其它方法见hibernateapi javadoc文档.

         ■hibernate.cfg.xml文件

         ①该文件主要用于指定各个参数,是hibernate核心文件

         ②默认放在src目录下,也可以放在别的目录下。

         ③指定连接数据库的驱动、用户名、密码、url、连接池..

         ④指定对象关系映射文件的位置.

         ⑤也可使用hibernate.properties文件来替代该文件.(推荐使用

hibernate.cfg.xml)。

        

         ■hibernate.properties文件

         作用和hibernate.cfg.xml一致.

         一个具体的实例,请参看hibernate.properties文件

        

         ■ 对象关系映射文件(*.hbm.xml)

  ①该文件主要作用是建立表和类的映射关系,是不可或缺的重要文件.

  ②一般放在其映射的类同一个目录下,但不是必须的。

  ③命名方式一般是 类名.hbm.xml,但不是必须的。

  ④示意图:


 SessionFactory(会话工厂)接口

①缓存sql语句和某些数据

          ②在应用程序初始化的时候创建,是一个重量级的类(吃内存),一般

 用单例模式保证一个应用中只需要一个 SessionFactory实例.

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

 是一个数据库一个会话工厂实例.

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

          ⑤如何理解会话工厂见下一个ppt

 示意代码: Configuration cf=newConfiguration().configure();

                       SessionFactory sf=cf.buildSessionFactory();

                       Session s=sf.getCurrentSession();

                       //或者是: Session s=sf.openSession();

 它的其它方法见 hibernate api javadoc文件


Session(会话)接口

①Session一个实例代表与数据库的一次操作

(当然一次操作可以是crud组合)

  ②Session实例通过SessionFactory获取,用完

需要关闭。

  ③Session是线程不同步的(不安全),因此要保证

在同一线程中使用,可以用getCurrentSessiong()。

  ④Session可以看做是持久化管理器,它是与持久

化操作相关的接口

         ⑤如何理解看下一个ppt

         示意代码:Configuration cf=new Configuration().configure();

                         SessionFactorysf=cf.buildSessionFactory();

                         Session s=sf.getCurrentSession();

                         //或者是: Sessions=sf.openSession();


 get()和load()区别
1、get()方法直接返回实体类,如果查不到数据则返回null。load()会

 

         返回一个实体代理对象(当前这个对象可以自动转化为实体对象),

 

         但当代理对象被调用时,如果没有数据不存在,就会抛出个

 

         org.hibernate.ObjectNotFoundException异常

 

 

2.load先到缓存(session缓存/二级缓存)中去查,如果没有则返回一个

 

         代理对象(不马上到DB中去找),等后面使用这个代理对象操作的时

 

         候,才到DB中查询,这就是我们常说的 load在默认情况下支持延迟加

 

         载(lazy)

 

3.get先到缓存(session缓存/二级缓存)中去查,如果没有就到DB中去

 

         查(即马上发出sql)。总之,如果你确定DB中有这个对象就用

 

         load(),不确定就用get()(这样效率高)      
penSession()和 getCurrentSession()区别

         ①采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()创建的session则不会

         ②采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()创建的session必须手动关闭.

         ③使用getCurrentSession()需要在hibernate.cfg.xml文件中加入

         如下配置:

         *如果使用的是本地事务(jdbc事务)

         <propertyname="hibernate.current_session_context_class">thread</property>

         *如果使用的是全局事务(jta事务)

         <propertyname="hibernate.current_session_context_class">jta</property>

         简单解释一下jdbc事务和jta事务的区别吧!

openSession()和 getCurrentSession()联系

         深入探讨:

         在SessionFactory启动的时候,Hibernate 会根据配置创建相应的 CurrentSessionContext,在getCurrentSession()被调用的时候,实际被执行的方法是 CurrentSessionContext.currentSession()。在

currentSession()执行时,如果当前Session为空,currentSession会调用SessionFactory的openSession。

openSession()和 getCurrentSession()究竟选谁?

        

         原则:

         ①如果需要在同一线程中,保证使用同一个Session

则,使用getCurrentSession()

         ②如果在一个线程中,需要使用不同的Session,则

使用opentSession()

 

■ openSession()和 getCurrentSession()联系

         用ThreadLocal模式 (线程局部变量模式) 管理Session,代码如下:

         publicclass HibernateUtil {

         publicstatic final ThreadLocal session =new ThreadLocal();

         publicstatic final SessionFactory sessionFactory;

  static {

     try {

       sessionFactory = newConfiguration().configure().buildSessionFactory();

     } catch (Throwable ex) {

          throw new ExceptionInInitializerError(ex);

     }    

         }

 public static Session currentSession() throws HibernateException {

       Session s = session.get();

       if(s == null) {

         s = sessionFactory.openSession();session.set(s);}

        return s;}

   public static void closeSession() throws HibernateException {

          Session s = session.get();

       if(s != null) { s.close();}

       session.set(null); }}

■ Transaction(事务)接口

这里我们简单给大家说明一下什么是事务。我们通过一个网上转账的

案例来说明.

         事务简单的说,就是一组对数据库的操作集合,它们要么全部成功,要

么全部失败.这个可以保证数据的一致性,事务具有原子性。

         ①Transaction是底层的事物实现中抽象出来的接口

         ②可能是一个jdbc或者jta的事务,这样有利于hibernate在不同执行

环境的移植。

         ③hibernate要求显示的调用事务(如果仅仅是查询可以不调用.)

         Transactionts=s.beginTransaction();

         ...

         ts.commit();s.close(); 发生异常需要ts.rollback()回滚.

 

■ Query接口

Query接口类型的对象可以对数据库操作,它可以使用Hql,Qbc,Qbe

和原生SQL(native Sql)对数据库操作.官方推荐使用Hql语句。

        

         这里我们给大家举例简单说明,后面有一个章节专门讲解Hql的使用

,Query接口查询出来的结果是一个List接口类型的对象。

■ Criteria接口

Criteria接口也可用于面向对象方式的查询,关于它的具体用法我们

 

这里先不做介绍,简单看几个案例.

 

         最简单案例:返回50条记录

 

         Criteria crit = sess.createCriteria(Cat.class);

 

         crit.setMaxResults(50);

 

         List cats = crit.list();

 

         限制结果集内容

 

         List cats =sess.createCriteria(Cat.class)

 

  .add( Restrictions.like("name","Fritz%") )

 

  .add(Restrictions.between("weight", minWeight, maxWeight) )

   .list();

 

 HQL和Criteria

HQL(Hibernate Query Language)-官方推荐

         面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写);HQL中查的是对象而不是表,并且支持多态;HQL主要通过Query来操作,Query的创建方式:

         Queryq = session.createQuery(hql);

from Person

from User user where user.name=:name

from User user where user.name=:name anduser.birthday < :birthday

Criteria

         Criteria是一种比HQL更面向对象的查询方式;Criteria的创建方式:

         Criteriacrit = session.createCriteria(DomainClass.class);

         简单属性条件如:criteria.add(Restrictions.eq(propertyName,value)),

         criteria.add(Restrictions.eqProperty(propertyName,otherPropertyName))

HQL详解

■  hql语句的详解

a.检索类的全部属性

b.检索类的部分属性

c.使用函数

d.模糊查询 like 属性 ‘%_’

查询所有刘姓学生 from Studentwhere sname like ‘刘%’;

e. group by , order by ....更多

为了能够更好的讲解hql语句,我们建立三张表,模拟一个简单

的学生选课系统.(见sql.txt文件)

 

■ 检索类的全部属性

         ①使用HQL语句可以检索出一个类(Student)的所有属性:

         (1).   from Student

         (2).   from Student where .......

■ 检索类的部分属性

         ①使用HQL语句可以检索出一个类(Student)的部分属性:

         (1)select  属性1,属性2  from Student

         比如:selectsname,saddress from Student在取出结果的时候要使用Iterator来取出,也可用,List.size()取出.

Iterator it=l.list().iteratiro();

         while(it.hasNext){

        Object []obj=(Object[])it.next();

        String sname=obj[0];

         String saddress=obj[1];

      }

 *分别使用for循环增强,和iterator来取.

■ uniqueResult方法

 

        当session.createQuery(“from xxxwhere cardid=‘xxx’”).uniqueResult();返回的结果只有一个对象时,可以使用uniqueResult()得到该对象。但是,如果结果是多条,使用该方法就会抛出异常。

*效率高,找到一条就返回,不会向下继续查询.

 

■ 过滤重复值/between..and

         ①当要过滤重复的数据时,可以使用distinct关键字:

         比如,显示所有学生的性别和年龄.  

        ②计算年龄在20~22之间的学生:

                  

         ③in 和not in

         查询计算机系和外语系的学生信息

select ssex, sage from Student;

         有重复记录,

         使用 selectdistinct ssex,sage from Student;

select sname,sage from Student where sagebetween 20 and 22;

select from Student where sdept in (‘计算机系’,’外语系’)

■ 模糊查询,orderby..

         ①group by

         显示各个系的学生的平均年龄:

        

         ②having的使用

         1.对分组查询后的结果,进行筛选:比如请显示人数大于3的系名称

        

         2.查询女生少于200人的系

select avg(sage), sdept from Student groupby sdept;

select sdept  from Student group by sdept having count(*) >3;

select sdept  from Student  where ssex=‘F’ group by

         sdepthaving count(*)<200;

■ 聚集函数的使用

         count(),avg(),max(),min(),sum();

         1.查询计算机系共多少人?

         2.查询总学分是多少?

         3.查询选修11号课程的最高分和最低分.

         4.显示各科考试不及格学生的名字,科目和分数

         5.计算各个科目不及格的学生数量.(学生练习!)

 selectcount(*),’计算机系’ from Student where sdept=‘计算机系’;

select sum(grade) ,’总学分’ fromStuCourse ;

select min(grade),max(grade) from StuCoursewhere course.cno=‘11’

select student.name,course.name,grade fromStuCourse where grade<60;

■ 分页显示对象
         根据用户输入的pageNow 和pageSize 显示对象

 

 

  Query q=session.createQuery(hql);

 

  q.setFirstResult(从第几条取//从0开始计算);

 

  q.setMaxResult(取出几条);

 

  List list=q.list();

 

  //list就是显示结果

 

  q=session.createQuery(得到count(*)的查询语句);

 

  int pageRow=((Integer)q.list().get(0)).intValue();

 

 

public void showStuByPage(int pageSize,intpageNow){

         Queryq=session.createQuery(“from Student”);

         q.setFirstResult((pageNow-1)*pageSize);//从第几条取

         q.setMaxResult(pageSize);   //取出几条

         Listlist=q.list();                  //执行   

         Iteratorit=list.iterator();        //显示一下

         while(it.hasnext){

                   Students=(Student)it.next();

                   System.out.println(s.getSname());

                   System.out.println(s.getSage());......

         }

         Stringhql=“select count(*) from Student”;

         list=session.createQuery(hql).list();

         intpageRow=((Integer)list.get(0)).intValue();

         intpageCount=(pageRow+pageSize-1)/pageSize;//总页数

         }

■ 参数绑定

可以用setParameter()的方法来确定变量的值:

Query q=session.createQuery(from Studentwhere sdept=:dept and sage>:age)

q.setParameter(参数名,值)

比如查询计算机系,年龄大于20的人.

提示:也可使用setInteger(),setString() ...来指定值.

另外: hql语句也可用? 来指定待绑定的参数:

String hql=“form Student wheresdept=:dept and sage>:age”;

Query q=session.createQuery(hql);

q.setParameter(“dept”,”计算机系”);

q.setParameter(“age”,newInteger(20));

List list=q.list();

String hql=“form Student wheresdept=? and sage>?”

q.setParameter(1,”计算机系”);

q.setParameter(2,new Integer(20));

List list=q.list();

■ 在映射文件中得到hql语句

可以从映射文件中得到hql,执行查询语句,这样可以更加灵活,在某些情况下,可以考虑使用:比如在: Student.hbm.xml 中

         <queryname="myquerytest">

         <![CDATA[selectsname,ssex from Student where sage>22]]>

         </query>

         如何使用:

         Listlist=session.getNamedQuery("myquerytest").list();

                   System.out.println(list.size());

                   Iteratorit=list.iterator();

                   while(it.hasNext()){

                            Objectobj[]=(Object[])it.next();

                            System.out.println("n="+obj[0]);

         }

■ 使用子查询

         可以在sql中,我们经常使用子查询处理复杂的查询要求,在hql中,我们一样可以使用子查询来完成复杂查询要求:

         比如:请显示所有选择了21号课程的学生信息。

from Student where sid in (selectstudent.sid from StudCourse where course.cno='21')

 

对于简单的表(没有外键或是被别的表关联的表),比如第二讲的admin【管理员表】和 employee【雇员表】就是简单的POJO 。但是我们项目中很多表和别的表都会有关联,在hibernte中的对象存在三种关系

 

         ①one-to-one

 

         ②one-to-many 【many-to-one】

 

         ③many-to-many [课程 --- 学生 中间表]

 

         并且还有所谓的单向和双向之分:

 

         我们的Student【学生表】和 Course【课程表】就是多对多,多对多一般都会通过一个中间表转成one-to-many 和 many-to-one比如.我们这里用了一个 中间表 StudCourse【学生-课程表】把关系简化成 one-to-many 和 many-to-one ,我们看看对象配置文件可以看出


多表查询


 

         studCourse作为中间表,将多对多的关系简化成 one-to-many和

many-to-one 的关系,这个也是在表的设计中惯用的一种数据库设计模式,下面我们就看看hql 如何处理多表查询的问题。

在项目开发过程中,我们不可能只对一张表进行操作,一定有多张表联合查询,下面看看在hql中如何对多表查询:

         比如: 请显示林青霞 选择的所有课程名,和成绩。

"selects1.sname,s2.course.cid,c1.cname,s2.grade from Student

as s1,StudCourse as s2,Course as c1 wheres1.sname='林青霞'

and s1.sname=s2.student.sname andc1.cid=s2.course.cid“

简单的:select s1.course.cname,s1.grade from Studcourse s1

where s1.student.sname='林可欣'

         由于一共涉及到三张表【类】,所以显得比较复杂,三步给大家讲解:

         ①显示林青霞选修的所有课程id号

         ②再显示课程的名称 (引入Course类)

         ③再显示各科成绩 (加深理解)

Criteria

Criteria

         Criteria是一种比HQL更面向对象的查询方式;Criteria的创建方式:

         Criteriacrit = session.createCriteria(DomainClass.class);

         简单属性条件如:criteria.add(Restrictions.eq(propertyName,value)),

         criteria.add(Restrictions.eqProperty(propertyName,otherPropertyName))

 Criteric 优点是更加面向对象,如果你的hql语句不太了解,可以使

用。缺点是: 功能不如hql强大.而且hql是hibernate官方推荐使用的

语句。

 

/***查询年龄大于10岁的学生*******

Criteriacriteria=session.createCriteria(Student.class);

criteria.add(Restrictions.ge("sage",10l));

List<Student> list=criteria.list();

for(Student s: list){

System.out.println(s.getSname());

}

6开发hibernate的三种方式

开发方式

         1由Domainobject -> mapping->db。(官方推荐)

         2由DB开始,用工具生成mapping和Domainobject。(使用较多)

         3由映射文件开始。

 

由Domain Object->mapping-db 需要配置

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

    hbm2ddl.auto其中有四个属性分别有validate,update,create,create-drop

 <propertyname="hbm2ddl.auto">create</property>

    hbm2ddl.auto其中有四个属性分别有validate,update,create,create-drop。

在sessionFactory 建立的时候自动检查数据库表结构,或者将数据库schema的DDL导到数据库中,

使用create-drop时,在显示关闭 sessionFactory时,将drop掉数据库的schema,

create顾名思义,每次都会根据映射文件创建新表.

update是数据库中表已经存在了,如果配置文件改变了(增加了一个属性,相当于再数据库中加了一个字段)那么update会自动在数据库中加上这个字段,

validate相当于每次插入数据之前都会验证数据库中的表结构和hbm文件的结构是否一致

 

基本概念和CURD细节详解

Domain Object限制

         1.默认的构造方法(必须的)。

         2有无意义的标示符id(主键)

         DomainJava Object(User)

public class User {

         privateint id;

         privateString name;

         privateDate birthDay;

         //gettersetter…

}

1.hbm.xml

<?xml version="1.0"?>

<hibernate-mapping package=“cn.hsp.domain">

<class name="User"table="user">

         <idname="id">

                   <generatorclass="native"/>

         </id>

         <propertyname="name“ />

         <propertyname="birthday”/>

</class>

</hibernate-mapping>

主键生成器,参考文档P65 5.1.4

2.详细信息见参考文档P62

*简单说一下即可.[可以演示如果不指定表名和属性的类型,也可以映射出表,由hibernate自己来检测.]

 

Java代码

         1.初始化代码(只做一次)

          Configuration cfg = new Configuration();

          cfg.configure(“config.cfg.xml”);

          也可以通过cfg.setProperty设置属性。

          SessionFactory sessionFactory =cfg.buildSessionFactory();         

         2.模板代码

Session session = null;Transaction tx =null;

try{

         session= sessionFactory.openSession();

         tx= session.beginTransaction();

         //…你的代码save,delete,update,get…

         tx.commit();

}catch(Exception e){

         if(tx!=null)tx.rollback();throw e;

}finally{

         if(session!= null)session.close();

}

对象状态

瞬时(transient):数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,一般是new出来且与session没有关联的对象。

持久(persistent):数据库中有数据与之对应,当前与session有关联,并且相关联的session没有关闭,事务没有提交;持久对象状态发生改变,在事务提交时会影响到数据库(hibernate能检测到)。

 脱管/游离(detached):数据库中有数据与之对应,但当前没有session与之关联;脱管对象状态发生改变,hibernate不能检测到。

 

 

//***********************************************

 

 

//使用Query 接口(PreparedStatement),完成hql(sql)语句查询

 

//hql入门案例,检索用户名是shunping的雇员

 

Session session = null;

 

Transaction ts=null;

 

try {

 

Employee emp=new Employee();

 

emp.setEmail("abc");

 

emp.setHiredate(new java.util.Date());

 

emp.setName("中国");

 

 

session=HibernateUtil.getThreadLocalSession();

 

ts=session.beginTransaction();

 

System.out.println("===========");

 

session.save(emp);

 

emp.setName("天龙八部");

 

ts.commit();

 

System.out.println("*************");

 

emp.setName("kkk");

 

} catch (Exception e) {

 

e.printStackTrace();

 

if(ts!=null){

 

ts.rollback();

 

}

 

// TODO: handle exception

 

}finally{

 

 

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

 

session.close();

 

}

 

}

 

7Hibernate关系映射

多对一(Employee - Department)

一对多(Department-Employee)

一对一(Person - IdCard)

多对多(teacher - student)

cascade(Employee – Department)

 

多对一(Employee - Department)

Employee映射文件

<many-to-one name=”depart” column=”depart_id”/>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值