Hibernate_7

JDBC API提供了一种可滚动的结果集,它是利用数据库系统中的游标来实现的。游标用于定位查询结果集中的记录,应用程序可以通过任意移动游标来定位到特定记录。

Query接口及Criteria接口的scroll()方法返回一个org.hibernate.ScrollableResults对象,它就代表可滚动的结果集。ScrollableResult接口包含一下用于移动游标的方法:
first():使游标移动到第一行
last():使游标移动到最后一行
beforeFirst():使游标移动到结果集的开头
afterLast():使游标移动到结果集的末尾
previous():使游标从当前位置向上移动一行
next():使游标从当前位置向下移动一行
scroll(int n):使游标从当前位置移动n行。若n>0,就向下移动,否则就向上移动。当n=1,等价于调用next()方法;当n=-1,等价于调用previous()方法
setRowNumber(int n):使游标移动到行号为n的行。参数n指定行号。结果集的行号从0开始编号。若n为0,使游标移动到第一行;若n为2,使游标移动到第三行;若n为-1,使游标移动到最后一行。
除beforeFirst()和afterLast()方法返回void类型,其余方法都返回boolean类型,若游标移动到的目标位置具有记录,就返回true,否则返回false。
final int PAGE_SIZE=3;
List firstNameOfPages = new ArrayList();
List pageOfCustomers = new ArrayList();
ScrollableResults re = session.createQuery("select c.name,c from Customer c").scroll();

if(rs.first()){
   do{
        String name = rs.getString(0);
        firstNamesOfPages.add(name);
     }while(rs.sroll(PAGE_SIZE));

rs.beforeFirst();
int i = 0;
while((PAGE_SIZE > i++) && rs.next())
  pageOfCustomers.add(rs.get(1)) ;
}

rs.close();

for(int i = 0 ;i < firstNamesOfPages.size();i++)
  System.out.println(firstNamesOfPages.get(i));

for(int i = 0 ;i < firstNamesOfPages.size();i++)
  System.out.println((Customer)PageOfCustomers.get(i)).getName();

Query接口及Criteria接口的scroll()方法还可以包含一个用于设置滚动模式的参数:
ScrollableResults rs = session.createCriteria(Customer.class).scroll(ScrollMode.FORWARD_ONLY);

org.hibernate.ScrollModel类提供了一下表示结果集滚动模式的静态常量:
ScrollMode.FORWORD_ONLY:游标只能从上到下移动,即结果集不能滚动,指示默认值
ScrollMode.SCROLL_INSENSITIVE:游标可以上下移动,即结果集可以滚动。当程序对结果集的内容做了修改,游标对此不敏感
ScrollMode.SCROLL_SENSITIVE:游标可以上下移动,结果集可以滚动。当程序对结果集的内容做了修改,游标对此敏感。

Hibernate采用绑定机制来避免恶意输入的问题。Hibernate的绑定机制依赖于JDBC API中PrepareStatement的预定于SQL语句。有以下优点:
非常安全,防止怀有恶意的用户非法调用数据库系统的存储过程
能够利用底层数据库预编译SQL语句的功能,提高查询数据的性能。预编译是指底层数据库系统只需编译SQL一次,把编译出来的可执行代码保存在缓存中,若执行相同形式的SQL,则不需重新编译,直接从缓存中获得可执行代码即可。

HQL的参数绑定有两种形式:
按参数名绑定:在HQL查询语句中定义命名参数,命名参数以:开头
Query query = session.createQuery("from Customer as c where c.name=: customerName and c.age =: customerAge");
query.setString("customerName",name);
query.setInteger("customerAge",age);

按参数位置绑定:在HQL查询语句中用个?来定义参数的位置
Query query = session.createQuery("from Customer as c where c.name = ? and c.age = ?");
query.setString(0 , name);
query.setInteger(1 , age);

除了用于绑定特定映射类型的参数方法,Hibernate还提供了3个特殊的参数绑定方法:
setEntity()方法:把参数与一个持久化类的实例绑定
setParameter()方法:绑定任意类型的参数。
//第三个参数显式指定Hibernate映射类型,有些参数值java可以推断出对应的映射类型,故可以不必显式指定。
query.setParameter("customer",customer,Hibernate.entity(Customer.class));
setProperties()方法:用于把命名参数与一个对象的属性绑定
Customer c = new Customer();
c.setName("Jack");
c.setAge(12);
List result = session.createQuery("from Customer as c where c.name =: customerName and c.age =: customerAge").setProperties(c).list;

在HQL检索方式或QBC检索方式来检索数据时,可以通过Query或Criteria接口的一些方法来设定查询附属事项:
setFlushMode()方法:设置清理缓存的模式
setCacheModel()方法:设置Session与第二级缓存的交互模式
setTimeout()方法:设置执行查询数据库操作的超时间
setFetchSize()方法:为JDBC驱动程序设置批量抓取的数目
setLockMode()方法:设置锁定模式
setComment()方法:为SQL日志设置注解
setReadOnly()方法:设置查询结果是否只允许读,它还可以设置单个持久化对象的读写模式:
setReadOnly(object,true);
setReadOnly(object,false):

Session的缓存有3种清理模式:分别用org.hibernate.FlushMode类的3个静态常量来表示:FlushMode.AUTO、FlushMode.NEVER
                   3种清理模式
清理缓存的模式 各种查询方法  Transaction的commit()方法  Session的flush()方法
FlushMode.AUTO   清理               清理                         清理
FlushMode.COMMIT  不清理            清理                         清理
FlushMode.NEVER   不清理           不清理                        清理

Query query = session.createQuery("from Customer c")
                     .setFlushMode(FlushMode.COMMIT);
Criteria criteria = session.createCriteria(Customer.class)
                           .setFlushMode(FlushMode.COMMIT);

Session与第二季缓存的5种交互模式及,分别用org.hibernate.CacheMode.NORMAL(正常模式)、CacheMode.IGNORAL(忽略模式)、CacheMode.GET(读取模式)、CacheMode.PUT(写入模式)、CacheMode.REFRESH(刷新模式)
Query query = session.createQuery("from Customer c")
                     .setCacheMode(CacheMode.GET)
                     .setFlushMode(FlushMode.COMMIT);
Criteria criteria = session.createCriteria(Customer.class)
                           .setCacheMode(CacheMode.GET);
                           .setFlushMode(FlushMode.COMMIT);


设置注解
在Hibernate配置文件中把hibernate.use_sql_comments属性设为true
Java属性格式的配置文件:
hibernate.use_sql_comments = true;
XML格式的配置文件:
<property name="use_sql_comments">true</property>

Hibernate允许在映射文件中定义字符串形式的查询语句。
<query name="findCustomerByName
       cache-mode="get"
       comment="My Comment.."
       fetch-size="50"
       read-only="true"
       timeout="60"
">
    <![CDATA[
          from Customer where c.name like :name
    ]]>
</query>

Query query = session.getNamedQuery("findCustomersByName");
query.setString("name",name);
List result = query.list();

字符串匹配模式:HQL用like关键字进行模糊查询,QBC用Restrictions类的like()方法进行模糊查询
%匹配任意类型并且任意长度的字符串,若是中文,需两个百分号(%%)
_匹配单个任意字符,常用来限制字符串表达式的长度
session.createQuery("from Customer c where c.name like '%T'");

Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.like("name","%T"));

对于QBC检索方式,除了使用通配符,还可以使用org.hibernate.criterion.MatchMode类的各种静态常量实例来设定字符串模式。
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.like("name","T",MatchMode.START));

             MatchMode类包含的各个静态常量实例
匹配模式                        举例
MatchMode.START    Restrictions.like("name","T",MatchMode.START) 以T开头
MatchMode.END      Restrictions.like("name","T",MatchMode.END) 以T结尾
MatchMode.ANYWHERE Restrictions.like("name","T",MacthMode.ANTWHERE) 包含T
MatchMode.EXACT    Restrictions.like("name","Tom",MatchMode.EXACT) 精准匹配

List result = session.createQuery("from Customer c where c.orders is empty").list();

List result = session.createCriteria(Customer.class).add(Restrictions.isEmpty("orders")).list();

              HQL与QBC支持的各种连接模型
在程序中指定的连接查询类型              HQL               QBC            
内连接                      inner join 或 join     Criteria.createAlias()
迫切内连接          inner join fetch 或 join fetch       不支持     
隐式内连接                            支持                    不支持  
左外连接              left outer join 或 left join       不支持
迫切左外连接  left outer join fetch 或 left join fetch  FetchMode.JOIN
右外连接              right outer join 或 right join      不支持
以上适用于有关联关系的持久类,并且在映射文件中对这种关联关系做了映射
交叉连接                   Class A, Class B                不支持
适用于不存在关联关系的持久化类

在使用left join fetch关键字表示迫切左外连接检索策略时,查询结果中可能会包含重复元素,可以通过一个HashSet来过滤重复元素。
List result = session.createCriteria(Customer.class)
                     .setFetchMode("orders",FetchMode.JOIN)
                     .add(Restrictions.like("name","T",MetchMode.START))
                     .list();

HashSet set = new HashSet(result);

for(Iterator it = set.iterator(); it.hasNext();){
  Customer customer = (Customer)it.next();
  ....
}

迫切左外连接和左外连接的区别是前者实例化里关联和被关联对象,后者只是返回一个引用。

猜你喜欢

转载自forever1121.iteye.com/blog/2117322