Hibernate开发指南笔记

一对一
 name 映射属性
 class 目标映射类。
 cascade 操作级联关系。可选值:
  all:所有情况下均进行级联操作。
  none:所有情况都不进行级联操作。
  save-update:在执行save-update时进行级联操作。
 constrained 约束。
 outer-join 是否使用外联接。
 property-ref 关联中用于主控类相关联的属性名称。
 access  属性值的读取方式。

新增一个对象:
 Transaction tx = session.beginTransaction();
 TAddress addr = new TAddress();

 addr.setTel("1123");
 addr.setZipcode("233123");
 addr.setAddress("HongKong");

 user.getAddress().add(addr);
 session.save(user);

 tx.commit();

两种方法来保存:
 sava(user)时候;
 insert into t_address(user_id,address,zipcode,tel) values(1,"Hongkong","233123","1123")

 tx.commit()时:
 update t_address set user_id="1",address="Hongkong",zipcode="233123",tel="1123" where id = 2

PO和VO概念

 PO 即Persistence Object  即纳入Hibernate管理框架中的VO.
 VO 即Value Object    就是一个简单的值的对象.

Locking锁
 悲观锁和乐观锁.
 悲观锁的调用:
 select * from accout where name="Erica" for update
 这条sql 语句锁定了account 表中所有符合检索条件(name=”Erica”)的记录。

 Hibernate的悲观锁,也是基于数据库的锁机制实现。
 下面的代码实现了对查询记录的加锁:
 String hqlStr = "from TUser as user where user.name='Erica'";
 Query query=session.createQuery(hqlStr);
 query.setLockMode("user",LockMode.UPGRADE);//枷锁
 List userList = query.list();//执行查询.获得数据


何谓数据版本?
 即为数据增加一个版本标识,在基于
 数据库表的版本解决方案中,一般是
 通过为数据库表增加一个“version”字段来
 实现。

optimistic-lock属性有如下可选取值:
  none
 无乐观锁
  version
 通过版本机制实现乐观锁
  dirty
 通过检查发生变动过的属性实现乐观锁
  all
 通过检查所有属性实现乐观锁


Hibernate分页:
 我们可以通过Criteria.setFirstResult和Criteria.setFetchSize方法设定分页范围

 Criteria criteria = session.createCriteria(TUser.class);
 Criteria.add(Expression.eq("age","20"));
 //从检索中获得第100条纪录开始的20条纪录
 criteria.setFirstResult(100);
 criteria.setFetchSize(20);

 MySQLDialect中的getLimitString实现
 public String getLimitString(String sql, boolean hasOffset) {
  return new StringBuffer( sql.length()+20 )
  .append(sql)
  .append( hasOffset ? " limit ?, ?" : " limit ?")
  .toString();
 }

 Oracle9Dialect 中的getLimitString 实现,其中通过Oracle 特有的
 rownum子句实现了数据的部分读取。
 public String getLimitString(string sql,boolean hasOffset)
 {
  StringBuffer pagingSelect = new StringBuffer(sql.length()+100);
  if(hasOffset){
   pageingSelect.append("select * from (select row_,*, rownum rownum_ from(");
  }
  else
  {
   pagingSelect.append("select * from(");
  }
  pagingSelect.append(sql);
  if(hasOffset)
  {
   pagingSelect.append(
    " ) row_ where rownum <= ?) where rownum_ > ?"
   );
  }
  else
  {
   pagingSelect.append(" ) where rownum <= ?");
  }
  return pagingSelect.toString();
 }


Cache管理
 Cache往往是提高系统性能的最重要的手段
 Hibernate 中实现了良好的Cache 机制,我们可以借助Hibernate 内部的Cache
 迅速提高系统数据读取性能
 在Hibernate.cfg.xml中配制
 <hibernate-configuration>
 <session-factory>
 ……
 <property name="hibernate.cache.provider_class">
 net.sf.ehcache.hibernate.Provider
 </property>
 ……
 </session-factory>
 </hibernate-configuration>

 另外cache本身还需要配制
 <ehcache>
  <diskStore path="java.io.tmpdir"/>
  <defaultcache
   maxElementsInMemory="1000" //cache 中最大允许保存的数据数量
   eternal="false"     //cache中数据是否常量
   timeToIdleSeconds="120"   //缓存数据钝化时间
   timeToLiveSeconds="120"  //缓存书库的生存时间
   overflowToDisk="true"   //内存不足,是否启用磁盘缓存
  />
 </ehcache>

 之后,需要在我们的映射文件中指定各个映射实体的Cache策略:
 <class name=" org.hibernate.sample.TUser" .... >
  <cache usage="read-write"/>
  ....
  <set name="addresses" .... >
  <cache usage="read-only"/>
  ....
  </set>
 </class>

 cache usage可选值有以下几种:
 1. read-only
  只读。
 2. read-write
  可读可写。
 3. nonstrict-read-write
  如果程序对并发数据修改要求不是非常严格,只是偶尔需要更新数据,可以采用
  本选项,以减少无谓的检查,获得较好的性能。
 4. transactional
  事务性cache。在事务性Cache 中,Cache 的相关操作也被添加到事务之中,
  如果由于某种原因导致事务失败,我们可以连同缓冲池中的数据一同回滚到事务
  开始之前的状态。目前Hibernate 内置的Cache 中,只有JBossCache 支持
  事务性的Cache实现。


需要注意的是Hibernate 的数据库查询机制。
 我们从查询结果中取出数据的时候,用的最多的是两个方法:
 Query.list();   对于list 操作,需要一条SQL 完成。
 Query.iterate();  对于iterate 操作,需要n+1条SQL。

 对于list方法而言,实际上Hibernate是通过一条Select SQL获取所有的记录。
 并将其读出,填入到POJO中返回。
 而iterate 方法,则是首先通过一条Select SQL 获取所有符合查询条件的记录的
 id,再对这个id 集合进行循环操作,通过单独的Select SQL 取出每个id 所对应的记
 录,之后填入POJO中返回。


Session管理

  无疑,Session是Hibernate运作的灵魂,作为贯穿Hibernate应用的关键,Session
 中包含了数据库操作相关的状态信息。如对JDBC Connection 的维护,数据实体的状态维持
 等。
  对Session 进行有效管理的意义,类似JDBC 程序设计中对于JDBC Connection 的调
 度管理。有效的Session管理机制,是Hibernate应用设计的关键。
  在各种Session 管理方案中, ThreadLocal 模式得到了大量使用。ThreadLocal 是
 Java中一种较为特殊的线程绑定机制。通过ThreadLocal存取的数据,总是与当前线程相关,
 也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出
 现的并发访问问题提供了一种隔离机制。
  SessionFactory负责创建Session,SessionFactory是线程
 安全的,多个并发线程可以同时访问一个SessionFactory 并从中获取Session 实例。而
 Session并非线程安全,也就是说,如果多个线程同时使用一个Session实例进行数据存取,
 则将会导致Session 数据存取逻辑混乱。

 Hibernate官方开发手册的示例中,提供了一个通过ThreadLocal维护Session的好
 榜样:
 public class HibernateUtil {
  private static SessionFactory sessionFactory;
  static {
   try {
    // Create the SessionFactory
    sessionFactory = new
    Configuration().configure().buildSessionFactory();
   } catch (HibernateException ex) {
    throw new RuntimeException(
    "Configuration problem: " + ex.getMessage(),
    ex
   );
  }
 }

 public static final ThreadLocal session = new ThreadLocal();
 public static Session currentSession() throws HibernateException
 {
  Session s = (Session) session.get();
  // Open a new Session, if this Thread has none yet
  if (s == null) {
   s = sessionFactory.openSession();
   session.set(s);
  }
  return s;
 }
 public static void closeSession() throws HibernateException {
  Session s = (Session) session.get();
  session.set(null);
  if (s != null)
  s.close();
  }
 }

 在Filter 中管理Session 对于Web 程序而言就显得水到渠成
 public class PersistenceFilter implements Filter
 {
  protected static ThreadLocal hibernateHolder = new ThreadLocal();
  public void doFilter(ServletRequest request, ServletResponse
  response, FilterChain chain)
  throws IOException, ServletException
  {
   hibernateHolder.set(getSession());
   try
  {
  ……
  chain.doFilter(request, response);
  ……
 }
 finally
 {
  Session sess = (Session)hibernateHolder.get();
  if (sess != null)
 {
  hibernateHolder.set(null);
  try
 {
  sess.close();
 }
  catch (HibernateException ex) {
  throw new ServletException(ex);
 }
 }
 }
 }
 ……
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值