hql语句的语法

hql语句的语法

 

1、HQL查询的from子句数据库

from是最简单的语句,也是最基本的HQL语句。from关键字后紧跟持久化类的类名。数组

例如:缓存

from Person  代表从Person持久化类中选出所有的实例session

推荐为Person持久化类的每一个实例起别名,例如:并发

from Person as papp

p做为Person的实例的别名,所以也应该遵照Java的命名规则:第一个单词的首字母小写,后面每一个单词的首字母大写。函数

命名别名时,as关键字是可选的,但为了增长可读性,建议保留。工具

from 后还可同时出现多个持久化类,此时将产生一个笛卡尔积或跨表的链接,但实际上这种用法不多使用,由于一般咱们可能须要使用跨表的链接,此时能够考虑使用隐式链接或显示链接,而不是直接在from后紧跟多个表名。fetch

2、关联和链接ui

       Hibernate使用关联映射来处理底层数据表之间的链接,一旦咱们提供了正确的关联映射后,当程序经过Hibernate进行持久化访问时,将可利用Hibernate的关联来进行链接。

      HQL支持两种关联链接(join)的形式:隐式(implicit)与显示(explicit)。

隐式链接形式不适用join关键字,使用英文点号(.)来隐式链接来关联实体,而Hibernate底层将自动进行关联查询。以下HQL语句:

from Person p where p.myEvent.title > :title

上面的p.myEvent属性的实质是一个持久化实体,所以Hibernate底层隐式地自动进行链接查询。

显示链接则须要使用xxx join关键字,例如以下语句:

//使用显示链接

from Person p

inner join p.myEvent event

where event.happenDate < :endDate

使用显示链接时,能够为相关联的实体,甚至是关联集合中的所有元素指定一个别名。

Hibernate支持的HQL链接类型,可以使用以下几种链接方式:

inner join(内链接),可简写成join。

left outer join(左外链接),可简写成left join。

right outer join(右外链接),可简写成right join。

full join(全链接),并不经常使用。

使用显示链接时,还可经过HQL的with关键字来提供额外的链接条件,例如以下HQL语句:

from Person p

inner join p.myEvent event

with p.id > event.id

where event.happenDate < :endDate

       HQL语句中的with关键字的做用基本等同于SQL99中on关键字的做用:都是用于指定链接条件。经过在HQL语句中使用with关键字,可让HQL语句执行非等值链接查询。

      因为表链接的方式都是基于底层SQL来实现的,若是底层不支持这些外链接,那么执行对应的HQL时就会相应地引起异常。

 

3、隐式链接和显示链接有以下两点区别:

(1)隐式链接底层转换成SQL92的内链接,显示链接层将转换成SQL99的多表链接。

(2)隐式链接和显示链接查询后返回的结果不一样。

当HQL语句中省略select关键字时,使用隐式链接查询返回的结果是多个被查询实体组成的集合。

当HQL语句中省略select关键字时,使用显示链接查询返回的结果也是集合,但集合元素是被查询持久化对象、全部被关联的持久化对象所组成的数组。

 注意:

       对于Hibernate3.2.3之后的版本,若是关联实体是单个实体或单个的组件属性,HQL依然能够彷佛用英文点号(.)来隐式链接关联实体或组件;但若是关联实体是集合(包括1-N关联、N-N关联和集合元素时组件等),则必须使用xxx join来显示链接关联实体或组件。

       对于集合属性的,Hibernate默认采用延迟加载策略,解决办法:

       (2.1)能够在Hibernate映射文件中指定lazy="false"来关闭延迟加载。

       (2.2)使用join fetch,一般无须指定别名,由于相关联的对象不该当在where子句(或其余任何子句)中使用。并且被关联的对象也不会再被查询的结果中直接返回,而是应该经过其父对象来访问。

使用fetch关键字时,有以下几个注意点:

       fetch不该该与setMaxResults()或setFirstResult()共用。由于这些操做是基于结果集的,而在预先抓取集合类时可能包含重复的数据,即没法预先知道精确的行数。

       fetch不能与独立的with条件一块儿使用。

       若是在一次查询中fetch多个集合,能够查询返回笛卡尔积,所以请多加注意。

       对bag映射而言,同时join fetch多个集合时可能出现非预期结果,所以须要谨慎使用。

      full join fetch 与right join fetch是没有任何意义的。

程序里但愿预加载那些本来应延迟加载的属性,则能够经过fetch all properties来强制Hibernate当即抓取这些属性。例如:

from Document fetch all properties order by name

 

4、HQL查询的select子句

(1)select子句用于选择指定的属性或直接选择某个实体,固然select选择的属性必须是from后持久化类包含的属性。

例如:

select p.name from Person as p

(2)select能够选择任意属性,即不只能够选择持久化类的直接属性,还能够选择组件属性包含的属性。例如:

select p.name.firstName from Person as p

(3)在特殊状况下,若是select后只有一项(包括持久化实例或属性),则查询获得的集合元素就是该持久化实例或属性。

(4)若是select后有多个项,则每一个集合就是选择出的多项组成的数组。

例如:

select p.name,p from Person as p

执行该HQL语句获得的集合元素时相似于[String,Person]结构的数组,其中第一个元素时Person实例的name属性,第二个元素时Person实例。

注意:即便select后的列表项选出某个持久化类的所有属性,这些属性依然是属性,Hibernate不会将这些属性封装成对象。只有在select后的列表里给出持久化类的别名(其实就是实例名),Hibernate才会将该项封装成一个持久化实体。

(5)select支持将选择出的属性存入一个List对象中。

例如:

select new list(p.name, p.address) from Person as p

 (6)select支持将选择出的属性封装成对象,前提是该对象拥有支持这些属性的构造器。

例如:

select new ClassTest(p,name, p.address) from Person as p;

而ClassTest必须有以下的构造器:ClassTest(String s1, String s2)

(7)select还支持给选中的表达式命名别名。例如:

select p.name as personName from Person as p

这种用法与new map 结合使用更广泛。例如:

select new map(p.name as personName) from Person as p

执行上面的HQL语句返回的结果是集合,其中集合元素时Map对象,以personName做为Map的key,实际选出的值做为Map的value。

 

 

5、HQL查询的汇集函数

HQL支持的汇集函数与SQL的彻底相同:avg,count,max,min,sum。

例如,以下的HQL语句:

select count(*) from Person

select max(p.page) from Person as p

select子句还支持字符串链接符、算术链接符,以及SQL函数。例如:

select p.name||""||p.address from Person as p

select子句也支持使用distinct和all关键字,此时的效果与SQL的效果彻底相同。

 

 

6、多态查询

       HQL语句被设计成可以理解多态查询,from后跟持久化类名,不只会查询出该持久化类的所有实例,还会查询出该类的子类的所有实例。

以下面的查询语句:from Person as p

       若是Named接口有多个持久化实现类,下面的语句将返回这些持久化类的所有实例。

以下面的查询语句:from Named as n

注意:上面最后一条查询,须要多个SQL SELECT 语句,所以没法使用order by子句对结果集排序,从而不容许对这些查询结果使用Query.scroll()方法。

 

 

7、HQL查询的where子句

(1)where子句用于筛选选中的结果,缩小选择的范围。若是没有为持久化实例命名别名,则能够直接使用属性名来引用属性。

以下面两条HQL语句:

from Person where name like "tom%"

form Person as p where p.name like "tom%"

(2)复合属性表达式增强了where子句的功能,例如,以下的HQL语句:

from Cat cat where cat.mate.name like "kit%"

上面语句被翻译成如下含有内链接的SQL查询:

select * from cat_table as table1 cat_table as table2

where table1.mate = table2.mate

and table1.name like '''kit%'"

实际上这种用法使用了隐式链接查询,从Hibernate3.2.3以后,只有当cat,mate属性引用的是普通组件属性或者单独的关联实体时才可接着在后面使用点好(.)来引用mate属性,如cat,mate.name; 若是cat,mate是集合属性,Hibernate3.2.3之后的版本不支持这种用法。

"="号不只能够被用来比较属性的值,也能够用来比较实例。

select cat,mate from Cat cat, Cat mate where cat.mate = mate

(3)在进行多态持久化的状况下,class关键字用来存取一个实例的鉴别值。嵌入where子句的Java类名,将被做为该类的鉴别值。

//执行多态查询时,默认会选出Cat及其全部子类的实例

//在以下HQL语句中,将只选出DomesticCat类的实例

from Cat cat where cat.class = DomesticCat

(4)当where子句中的运算符只支持基本类型或者字符串时,where子句中的属性表达式必须以基本类型或者字符串结尾,不要使用组件类型属性结尾,例如Account和Person属性,而Person有Name属性,Name属性有firstName属性。

以下所示:

//firstName是字符串

from Account as a where a.person.name.firstName like "dd%"

//下面是错误实例

from Account as a where a.person.name like "dd%"

 

 

8、表达式

一、HQL的功能很是丰富,where子句后支持的运算符,不只包括SQL的运算符,也包括EJB-QL的运算符等。

where子句中容许使用大部分SQL支持的表达式,包括以下种类:

(1)字符串链接:如value1||value2,或使用字符串链接函数concat(value1, value2)

(2)简单的case,case...when...then...else...end和case,case when...then...else...end等。

(3)时间操做函数:current_date()、current_time、year()等。

(4)EJB-QL3.0的函数:substring()、trim()、abs()、sqrt()等。

(5)可在where子句中使用SQL常量。

(6)在HQL语句中使用Java中的public static final类型的常量,例如Color.RED

(7)HQL语句支持使用英文问号(?)做为参数占位符,这与JDBC的参数占位符一致;也使用命名参数占位符号,方法在参数名前加英文冒号(:),例如:start_date等。

(8)若是底层数据库支持单行函数,则HQL语句也彻底能够支持。

(9)支持数据库的类型转换函数,如cast(... as ...),第二个参数是Hibernate的类型名,或者extract(... from ,,,),前提是底层数据库支持ANSI cast()和extract()。

二、若是在Hibernate配置文件中进行以下声明:

<property name="hibernate.query.substitutions">true 1,false 0</property>

上面的声明代表:HQL转换SQL语句时,将使用字符1和0来取代关键字true和false,而后将能够在表达式中使用布尔表达式。

三、有用的elements()和indices函数,用于返回指定集合的全部元素和全部索引。

四、在where子句中,有序集合(数组、List集合、Map对象)的元素能够经过【】运算符来访问。以下:

from Order order where order.items[0].id=1234

在【】中的表达式甚至能够是一个算式表达式。

五、结构变量:size、elements、indices等,只能在where子句中使用。

 

 

9、order by子句

查询返回的集合根据类或组件属性的任何属性进行排序。例如:

from Person as p order by p.name,p.age

还可使用as或desc关键字指定升序或降序的排序规则。例如:

from Person as p order by p.name asc,p.age desc

若是没有指定排序规则,默认采用升序规则。

10、group by子句

返回汇集值的查询能够对持久化类或组件属性的进行分组,分组使用group by子句。看下面的HQL查询语句:

select cat,color,sum(cat.weight),count(cat) from Cat cat group by cat.color

其规则相似于SQL规则。

having子句用于对分组进行过滤,以下所示:

select cat,color,sum(cat.weight),count(cat) from Cat cat group by cat.color having cat.color in (eg.Color.TABBY,eg.Color.BLACK)

注意:group by子句与order by 子句中都不能包含算术表达式

 

 

11、子查询

(1)若是底层数据库支持子查询,则能够在HQL语句中使用子查询。以下:

from Cat as fatcat where fatcat.weight > (select avg(cat.weight) from DomesticCat cat)

(2)若是子查询是多行结果集,则应该使用多行运算符。以下:

from Cat as cat where not(cat.name, cat.color) in (select cat.name, cat.color from DomesticCat cat)

(3)SQL语法中子查询还能够出如今select子句以后,HQL也支持这种用法,看以下HQL语句:

select cat.id,(select max(kit.weight) from cat.kitten kit)

from Cat as cat

注意:HQL子查询只能够在select子句或者where子句中出现。

 

12、命名查询

HQL支持将查询所用的HQL语句放入配置文件中,而不是代码中。

在Hibernate映射文件的<hibernate-mapping/>元素中使用<query/>子元素来定义命名查询,使 用<query/>元素只须要指定一个name属性,指定该命名查询的名字。该元素的内容就是命名查询的HQL语句。以下配置文件片断:

<query name="myNameQuery">

        from Person as p where p.age > ?

</query>

配置好后,经过Session提供的一个getNameQuery(String name)方法,该方法用于建立一个Query对象,剩下的操做与普通HQL彻底同样。以下所示:

List p1 = sess.getNamedQuery("myNameQuery").setInteger(0,20).list()

 

 

十3、条件查询

条件查询经过以下3个类完成:

Criteria:表明一次查询。

Criterion:表明一个查询条件。

Restrictions:产生查询条件的工具类。

执行条件查询的步骤以下:

(1)得到Hibernate的Session对象。

(2)以Session对象建立Criteria对象。

(3)使用Restrictions的静态方法建立Criterion查询条件。

(4)向Criteria查询中体检Criterion查询条件。

(5)执行Criteria的list等方法返回结果集。

代码片断以下:

List l = session.createCriteria(Student.class)

            //此处增长限制条件必须是Student已经存在的属性

             .add(Restrictions.get("studentNumber", 20050231L))

            //若是要增长对Student的关联类的属性的限制

            //则必须从新createCriteria()

            //若是此关联属性是集合,则只要集合里任意一个对象的属性知足下面条件便可

            .createCriteria("enrolments")

            .add(Restrictions.gt("semester",2))

            .list();

在条件查询中,Criteria接口表明依次查询,该查询自己不具有任何的数据筛选功能,Session调用createCriterial(Class clazz)方法对某个持久化类建立条件查询实例。

Criteria对象不具有任何的数据筛选功能,但程序能够经过向Criteria对象中组合多个Criterion(每一个Criterion对象表明一个过滤条件)便可实现数据过滤了。

Criterion接口表明一个查询条件,该查询条件由Restrictions负责产生。Restrictions是专门用于产生查询条件的工具类,它的方法大部分都是静态方法,经常使用的方法以下:

(1)static Criteion allEq(Map propertyNameValues):判断指定属性(由Map参数的key指定)和指定值(由Map参数的value指定)是否彻底相等。

(2)static Criterion between(String propertyName, Object lo, Object hi):判断属性值在某个指范围以内。

 

 

十4、关联和动态关联

代码片断以下:

List l = session.createCriteria(Student.class)

            //此处增长限制条件必须是Student已经存在的属性

             .add(Restrictions.get("studentNumber", 20050231L))

            //若是要增长对Student的关联类的属性的限制

            //则必须从新createCriteria()

            //若是此关联属性是集合,则只要集合里任意一个对象的属性知足下面条件便可

            .createCriteria("enrolments")

            .add(Restrictions.gt("semester",2))

            .list();

上面的代码表示创建Person类的条件查询,第一个查询条件是直接过滤Person的属性。第二个查询条件则过滤Person的关联实体的属性,其中 enrolments是Person类的关联实体,而semester则是Enrolment类的属性。值得注意的是,返回的并非Enrolment对 象,而是Person对象的集合。

注意:使用关联类的条件查询,依然是查询原有持久化类的实例,而不是查询被关联类的实例。

可以使用条件查询支持的替换形态,将上面查询代码替换成以下形式:

List l = session.createCriteria(Student.class)

            .add(Restrictions.gt("studentNumber",20050231L))

            .createAlias("enrolments","en")

            .add(Restrictions.gt("semester",2))

             .list();

createAlias()方法并不建立一个新的Criteria实例,它只是给关联实体(包含集合里包含的关联实体)起一个别名,让后面过滤条件可根据关联实体进行筛选。

在默认状况下,条件查询将根据映射文件指定的延迟加载策略来加载关联实体,若是但愿在条件查询中改变延迟加载策略(就像在HQL查询中使用fetch关键 字同样),那就可经过Creteria的setFetchMode()方法来实现,该方法接受一个FetchMode参数。

FetchMode里有几个常量,以下:

DEFAULT:使用配置文件制定的延迟加载策略处理。

JOIN:使用外链接,预初始化全部关联实体。

SELECT:启用延迟加载,系统将使用单独的select语句来初始化关联实体。只有当个真正访问关联实体的时候,才会执行第二条select语句。

初始化Student对象时,也能够初始化Student关联的Enrolment实体,实体使用以下代码:
List l = session.createCriteria(Student.class)

            .add(Restrictions.gt("studentNumber",20050231L))

            .setFetchMode("enrolments", FetchMode.JOIN)

            .list();

 

 

十5、投影、聚合和分组

投影运算实际上就是一个基于列的运算,一般用于投影到指定列(也就是过滤其余列,相似select子句的做用),还能够完成SQL语句中经常使用的分组、组筛选等功能。

Hibernate的条件过滤中使用Projection表明投影运算,Projection是一个接口,而Projections做为Projection的工厂,负责生成Projection对象。

一旦产生了Projection对象以后,就可经过Criteria提供的setProjection(Projection projection)方法来进行投影运算。从该方法上看,每一个Criteria只能接受一个投影运算,彷佛没法进行多个投影运算,但实际上 Hibernate又提供了一个ProjectionList类,该类是Projection的子类,并能够包含多个投影运算,经过这种方式即完成多个投 影运算。

所以,一个条件查询的投影运算一般有以下程序结构:

List cats = session.createCriteria(Cat.class)

                 .setProjection(Projections.projectionList()

                 .add(Projections.rowCount())

                 .add(Projections.avg("weight"))

                 .add(Projections.groupProperty("color"))

                  ).addOrder(Order.asc("color"))

                  .list();

注意:使用条件查询的投影运算时,不能使用显示的分组子句,但某些投影类型的实质就是分组投影,这些投影元素将出如今SQL的group by子句中——如上的groupProperty("color")投影。

投影运算的实质和group by子句、汇集函数的功能大体一致。

除此以外,若是咱们但愿对分组(投影)后属性进行排序,那就须要为投影运算指定一个别名。为投影运算指定别名有3种方法:

(1)使用Projections的alias()方法为指定投影指定别名。一旦为projection指定了别名,则程序就能够根据该Projection别名来进行其余额外操做了,好比排序。条件查询片断以下:

List l = session.createCriteria(Enrolment.class)

           .setProjection(Projections.projectionList()

            //按course进行分组

           .add(Projections.groupProperty("course"))

           //统计记录条数,并为统计结果指定别名c

           .add(Projections.alias(Projections.rowCount()," c"))

             ).addOrder(Order, asc("c"))

           .list();

(2)使用SimpleProjection的as()方法为自身指定别名。

List l = session.createCriteria(Enrolment.class)

           .setProjection(Projections.projectionList()

            //按course进行分组

           .add(Projections.groupProperty("course").as("c"))

           //统计记录条数,并为统计结果指定别名c

           .add(Projections.rowCount())

             ).addOrder(Order, asc("c"))

           .list();

(3)使用ProjectionList的add()方法添加投影时指定别名。

ProjectionList的add()方法有两个重载形式,一个是直接添加投影,另外一个是在添加投影时指定别名。条件查询片断以下:

List l = session.createCriteria(Enrolment.class)

           .setProjection(Projections.projectionList()

            //按course进行分组,指定别名为c

           .add(Projections.groupProperty("course"),("c"))

           //统计记录条数,并为统计结果指定别名rc

           .add(Projections.rowCount(),"rc")

             ).addOrder(Order, asc("c"))

           .list();

除此以外,Hibernate还提供了Property执行投影运算,Property投影的做用相似于SQL语句中的select,条件查询的结果只有被Property投影的列才会被选出,条件查询片断以下:

List l = session.createCriteria(Student.class)

            .setProjection(Property.forName("name"))

            .list();

上面条件查询执行的结果再也不是Student对象集合,而是name属性所组成的集合。

 

 

十6、离线查询和子查询

条件查询的离线查询由DetachedCriteria来表明,DetachedCriteria类使你在一个session范围以外建立一个查询,而且可使用任意的Session来执行它。

DetachedCriteria还可表明子查询,当咱们把DetachedCriteria传入Criteria中做为查询条件时,DetachedCriteria就变成了子查询。如下代码片断所示:

//定义一个离线查询

DetachedCriteria query = DetachedCriteria.forClass(Student.class)

                                         .forClass(Student.class)

                                         .setProjection(Property.forName("name"));

//打开Session和事务(省略)

//执行离线查询

List l = query.getExecutableCriteria(session).list();

//执行子查询

List l = session.createCriteria(Student.class)

           .add(Property.forName("name").in(query))

           .list();

若是程序使用Session的getExecutableCriteria()方法来执行DetachedCriteria对象,则它被当成离线查询使用;若是程序使用Property的系列方法来操做DetachedCriteria对象,则它被当成子查询使用。

 

 

十7、事务和Session

一、Session和用户请求是一对一得关系,这是一种理想的Session管理模式。

为了达到这种效果,推荐使用一个ThreadLocal变量,把Session绑定处处理客户端请求的线程上。这种方式可让运行在该线程上的全部程序代 码轻松地访问Session。也能够在一个ThreadLocal变量中保持事务上下文环境,不过这依赖于你所选择的数据库事务划分机制。这种实现模式被 称为ThreadLocal Session和Open Session in View。

工具类代码以下:
public class HibernateUtil

{

       //使用一个final变量来保存不可变的SessionFactory

       public static final SessionFactory sessionFactory;

static{

         try{

             //采用默认的Hibernate.cfg,xml来启动一个Configuration的实例

             Configuration conf = new Configuration().configure();

             //由conf实例建立一个SessionFactory实例

             sessionFactory = conf.buildSessionFactory();

             }catch(Throwable ex){

                     System.err.println("初始化SessionFactory出现异常:"+ex);

                     throw new ExceptionInitializerError(ex);

            }

         }

//ThreadLocal是隔离多个线程的数据共享

//不存在多个线程之间共享资源,所以再也不须要对线程同步

          public static final ThreadLocal session = new ThreadLocal();

          public static Session currentSession() throws HibernateException

          {

                Session s = (Session)session.get();

                //若是该线程尚未Session,则建立一个新的Session

                if(s == null)

                {

                    s = sessionFactory.openSession();

                //将得到的Session变量存储在ThreadLocal变量session里

                     session.set(s);

                 }

                 return s;

           }

           public static void closeSession() throws HibernateException

           {

                Session s = (Session)session.get();

                if(s != null)

                {

                       s.close();

                       session.set(null);

                }

           }

}

在上面的代码中,Hibernate Session被绑定到当前线程。当调用currentSession方法时,若是当前线程中的Session已经建立出来,那么将返回这个已经存在的Session实例。

注意:几乎全部状况下,都不要使用每一个应用对应一次Hibernate Session的模式,也不要使用每次Http Session对应一次Hibernate Session的模式。

二、对于以上的状况,Hibernate主要有以下3种模式来解决这个问题:

(1)自动版本化:Hibernate可以自动进行乐观并发控制,若是在用户思考的过程当中持久化实体发生并发修改,Hibernate可以自动检测到。

(2)脱管现象:若是采用每次用户请求对应一次Session的模式,那么,前面载入的实例在用户思考的过程当中,始终与Session脱离,处于脱管状 态。Hibernate容许把脱管对象从新关联到Session上,而且对修改进行持久化。在这种模式下,自动版本化被用来隔离并发修改。这种模式也被称 为脱管对象的每次请求对应一个Hibernate Session。

(3)长生命周期Session:Session能够在数据库事务提交以后,断开和底层的JDBC链接。当新的客户端请求到来时,它又从新链接上底层的 JDBC连接。这种模式被称为每一个应用程序事务对应一个Session。由于应用程序事务时至关长(跨越多个用户请求)的,因此也被称为长生命周期 Session。

注意:Session缓存了处于持久化状态的每一个对象(Hibernate会监视和检查脏数据),也就是说,若是程序让Session打开很长一段时间, 或者载入了不少数据,Session占用的内存会一直增加,直到抛出OutOfMemoryException异常。为了解决这个问题,程序按期调用 Session的clear()和evict()方法来管理Session的缓存。对于一些大批量的数据处理,推荐使用DML风格的HQL语句完成。

三、为了保证在Session关闭以前初始化代理属性或集合属性,程序能够Hibernate,initialized()静态方法来强制初始化集合或代 理。只要Session处于open状态,Hibernate.initialize(teahcer)将会强制初始化teacher代 理,Hibernate.initialize(teacher.getStudents())对student的集合具备一样的功能。

还有另外一种选择,就是程序让Session一直处于打开状态,直到装入全部须要的集合或代理。

保证Session处于打开状态有两种方法能够解决此问题:

(1)在一个Web应用中,能够利用过滤器(Filter),在用户请求结束、页面生成结束时关闭Session。也就是保证在视图层一直打开Session,这就是所谓的Open Session in View成视图界面的过程当中发生异常时,必须保证能够正确关闭Session,并结束事务。

(2)使用业务逻辑层来准备数据,在业务逻辑层返回数据以前,业务逻辑层对每一个所需集合调用Hibernate.initialize()方法,或者使用 带fetch子句或FetchMethod.JOIN的查询,事先取得全部数据,并将这些数据封装成VO(值对象)集合,而后程序能够关闭Session 了。业务逻辑层VO集传入视图层,让视图层只负责简单的显示逻辑。在这种模式下,可让视图层和Hibernate API完全分离,保证视图层不会出现持久层API,从而提供更好的解耦。

 

 

十7、上下文相关的Session

从Hibernate3.1开始,SessionFactory.getCurrentSession()的底层实现是可插拔的,Hibernate引入 了CurrentSessionContext接口,并经过hibernate_current_session_context_class参数来管理 上下文相关Session的底层实现。

CurrentSessionContext接口有以下3个实现类:

org.hibernate.context.JTASessionContext:根据JTA来跟踪和界定上下文相关Session,这和最先的仅支持JTA的方法是彻底同样的。

org.hibernate.context.ThreadLocalSessionContext:经过当前正在执行的线程来跟踪和界定上下文相关Session,也就是和前面的HibernateUtil的Session维护模式类似。

org.hibernate.context.ManagedSessionContext:经过当前执行的线程来跟踪和界定上下文相关的 Session。可是程序须要使用这个类的静态方法将Session实例绑定、取消绑定,它并不会自动打开、flush或者关闭任何Session。

对于容器中使用Hibernate的场景而言,一般会采用第一种方式:对于独立的Hibernate应用而言,一般会采用第二种方式。

为了指定Hibernate使用哪一种Session管理方式,能够在hibernate.cfg.xml文件中增长以下片断:

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

若是在JTA事务环境中,则应增长以下配置片断:

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

对于第三种不经常使用的Session管理机制,则可在配置文件中简写成:managed。

 

http://blog.163.com/xiaokangzhijia@126/blog/#m=0&t=1&c=fks_084066087085082071086094081095085080084074081082094070082

相关文章
相关标签/搜索