riteria 查询总结,能完成一般查询、统计、分组、多表查询

]二、Criteria 查询总结,能完成一般查询、统计、分组、多表查询


填入任一查询参数,模糊查询

Criteria criteria = getSession().createCriteria(User.class); 
criteria.add(Restrictions.eq("id",new Integer(1))); 
List list = criteria.list(); 
criteria.add(Restrictions. like("username",”%jiang%”));

您可以使用 Criteria 進行查詢,並使用 Order 對結果進行排序,例如使用 Oder.asc() 由小到大排序
(反之則使用 desc() ):

Criteria criteria = session.createCriteria(User.class); 
criteria.addOrder(Order.asc("age")); 
List users = criteria.list();


setMaxResults() 方法可以限定查詢回來的筆數,如果配合 setFirstResult() 設定傳回查詢結果
第一筆資料的位置,就可以實現簡單 的分頁,例如傳回第 51 筆之後的 50 筆資料(如果有的話):

Criteria criteria = session.createCriteria(User.class); 
criteria.setFirstResult(51); 
criteria.setMaxResult(50); 
List users = criteria.list();


您可以對查詢結果進行統計動作,使用 Projections 的 avg() 、 rowCount() 、 count() 、 max() 、 min() 、
countDistinct() 等方法,例如對查詢結果的 "age" 作平均:

Criteria criteria = session.createCriteria(User.class); 
criteria.setProjection(Projections.avg("age")); 
List users = criteria.list(); 
Iterator iterator = users.iterator(); 
while(iterator.hasNext()) { 
System.out.println(iterator.next()); 
}


還可以配合 Projections 的 groupProperty() 來對結果進行分組,例如以 "age" 進行分組,也就是如果資料中 "age" 
如果有 20 、 20 、 25 、 30 ,則以下會顯示 20 、 25 、 30 :

Criteria criteria = session.createCriteria(User.class); 
criteria.setProjection(Projections.groupProperty("age")); 
List users = criteria.list(); 
Iterator iterator = users.iterator(); 
while(iterator.hasNext()) { 
System.out.println(iterator.next()); 
}


如果想結合統計與分組功能,則可以使用 ProjectionList ,例如下面的程式會計算每個年齡各有多少個人:

ProjectionList projectionList = Projections.projectionList(); 
projectionList.add(Projections.groupProperty("age")); 
projectionList.add(Projections.rowCount()); 

Criteria criteria = session.createCriteria(User.class); 
criteria.setProjection(projectionList); 
List users = criteria.list(); 
Iterator iterator = users.iterator(); 
while(iterator.hasNext()) { 
Object[] o = (Object[]) iterator.next(); 
System.out.println(o[0] + "/t" + o[1]); 
}


如果有一個已知的物件,則可以根據這個物件作為查詢的依據,看看是否有屬性與之類似的物件,例如:

User user = new User(); 
user.setAge(new Integer(30)); 

Criteria criteria = session.createCriteria(User.class); 
criteria.add(Example.create(user)); 

List users = criteria.list(); 
Iterator iterator = users.iterator(); 
System.out.println("id /t name/age"); 
while(iterator.hasNext()) { 
User ur = (User) iterator.next(); 
System.out.println(ur.getId() + 
" /t " + ur.getName() + 
"/" + ur.getAge()); 
}


在這個例子中, user 物件中有已知的屬性 "age" 為 30 ,使用 Example 會自動過濾掉 user 的空屬性,
並以之作為查詢的依據,也就是找出 "age" 同為 30 的資料。 

Criteria 可以進行複合查詢,即在原有的查詢基礎上再進行查詢,例如在 Room 對 User 的一對多關聯中,
在查詢出所有的 Room 資料之後,希望再查詢 users 中 "age" 為 30 的 user 資料:

Criteria roomCriteria = session.createCriteria(Room.class); 
Criteria userCriteria = roomCriteria.createCriteria("users"); 
userCriteria.add(Restrictions.eq("age", new Integer(30))); 
List rooms = roomCriteria.list(); // 
只列出 users 屬性中有 user 之 "age" 為 30 的 Room 
Iterator iterator = rooms.iterator();


[size=+1]三、Hibernate 的事务管理

Hibernate 是 JDBC 的轻量级封装,本身并不具备事务管理能力。在事务管理层,

Hibernate 将其委托给底层的 JDBC 或者 JTA ,以实现事务管理和调度功能。

Hibernate 的默认事务处理机制基于 JDBC Transaction 。我们也可以通过配置文

件设定采用 JTA 作为事务管理实现:

< property name = "hibernate.transaction.factory_class" >

net.sf.hibernate.transaction.JTATransactionFactory

<!--net.sf.hibernate.transaction.JDBCTransactionFactory-->

</ property >

基于 JDBC 的事务管理

session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

……

tx.commit();

从 JDBC 层面而言,上面的代码实际上对应着:

Connection dbconn = getConnection();

dbconn.setAutoCommit( false );

……

dbconn.commit();

基于 JTA 的事务管理

JTA 提供了跨 Session 的事务管理能力。这一点是与 JDBC Transaction 最大的

差异。

JDBC 事务由 Connnection 管理,也就是说,事务管理实际上是在 JDBC Connection

中实现。事务周期限于 Connection 的生命周期之类。同样,对于基于 JDBC Transaction

的 Hibernate 事务管理机制而言,事务管理在 Session 所依托的 JDBC Connection

中实现,事务周期限于 Session 的生命周期。

JTA 事务管理则由 JTA 容器实现, JTA 容器对当前加入事务的众多 Connection 进

行调度,实现其事务性要求。 JTA 的事务周期可横跨多个 JDBC Connection 生命周期。

同样对于基于 JTA 事务的 Hibernate 而言, JTA 事务横跨可横跨多个 Session 。

因此当 open 多个 session 时候,用 JTA 来管理事务。

在 EJB 中使用 JTA Transaction 无疑最为简便,我们只需要将 save 方法配置为

JTA 事务支持即可,无需显式申明任何事务,下面是一个 Session Bean 的 save 方法,

它的事务属性被申明为“ Required ”, EJB 容器将自动维护此方法执行过程中的事务:

Hibernate 支持两种锁机制:即通常所说的“悲观锁( Pessimistic Locking )”

和“乐观锁( Optimistic Locking )”

悲观锁:保守态度,一旦上锁,外界无法修改,直到释放

乐观锁: Hibernate 在其数据访问引擎中内置了乐观锁实现。如果不用考虑外部系统对数

据库的更新操作,利用 Hibernate 提供的透明化乐观锁实现,将大大提升我们的

生产力。

< class

name = "org.hibernate.sample.TUser"

table = "t_user"

dynamic-update = "true"

dynamic-insert = "true"

optimistic-lock "version"

>

乐观锁,大多是基于数据版本

( Version )记录机制实现。

Cache 管理

使用 cache 的目的往往是为了提高系统的性能;

引入 Cache 机制的难点是如何保证内存中数据的有效性,否则脏数据的出现将给系统

带来难以预知的严重后果。

Hibernate 中的 Cache 大致分为两层,第一层 Cache 在 Session 实现,属于事务

级数据缓冲,一旦事务结束,这个 Cache 也就失效。

第二层 Cache ,是 Hibernate 中对其实例范围内的数据进行缓存的管理容器。

我们需要讨论的是第二层 Cache, 最简单是基于 HashTable 的 cache 机制 .

使用了 Cache 机制之后,应当注意编码的结合,特别在查询数据的时候使用:

Query.list(); 取出所有的数据 , 一次 sql

Query.iterate(); 两次 sql, 一次去 ID , 如果有 cache 则优先查找,二次才取数据

Session 管理

SessionFactory 负责创建 Session , SessionFactory 是线程

安全的,多个并发线程可以同时访问一个 SessionFactory 并从中获取 Session 实例。而

Session 并非线程安全,也就是说,如果多个线程同时使用一个 Session 实例进行数据存取,

则将会导致 Session 数据存取逻辑混乱。

我们可以通过应用 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();

}

}

对于 web 程序而言

我们可以借助 Servlet2.3 规范中新引入的 Filter 机制,轻松实现线程生命周期内的 Session 管理

[size=+1]四、再度思考

1 、对 ORM 的理解 

ORM ( Object Relational Mapping )简单的说,就是对象与关系的映射,对于实际应用来讲,
对象一般指面向对象中的对象,关系指关系型数据库,对于我们具体的项目来说,就是将 java 中的
对象与关系型数据库( oracle , mysql )中的表联系起来。

ORM 解决方案有以下四部分组成:

■ 在持续类的对象上执行基本的 CRUD 操作的一组 API 。

■ 用于指定查询的一种语言或一组 API ,这些查询会引用类和类属性。

■ 用于指定映射元数据的工具。

■ 实现 ORM 的一项技术,用来与事务对象交互以完成脏检查、懒关联存取和其它优化功能。

ORM 这种解决方案的好处:

对底层的封装,因此,可移植性好,厂商独立;

解决对象 - 关系不匹配问题;


在传统我们在持久层通常使用 SQL 和 JDBC ,通常认为这样方式已经让大家感到厌倦了,特别是烦琐的代码;

2 、 hibernate 可以认为是最优秀的 ORM 工具 

Hibernate 是一个雄心勃勃的项目,它的目标是成为 Java 中管理持续性数据问题的一种完

整的解决方案。它协调应用与关系数据库的交互,让开发者解放出来专注于手中的业务问题。

Hibernate 符合 java 编程习惯,它把数据库与一个 POJO (简单 Java 对象)关联起来,
使得对数据库进行 CRUD 等操作时候,直接操作 Java 对象就可以了。通过以前 Java Bean 一样 , 
使用 setter 和 getter 方法。 
[size=+1] 五、辅助工具

(1)自动生成 hibernate 的映射文件

一般考虑两个方向:从数据库到映射文件,从 java 类到映射文件

数据库到映射文件可以采用 Middlegen-Hibernate ,这个能很直观的看到表之间的关系,并且能适当的做修改;

从 java 类到映射文件的生成,可以用 XDoclet ,不过需要在 java 类中加上一些标记

从生成的映射文件自动生成 java 类,可以用用一些工具,如 hbm2java

从这四种自动生成工具来看,  mapping file, java file and DDL ,只要知道任何一种文件,都可以得到另外两种文件, 
如: 
1.  只有 mapping file: 
mapping file---hbm2java----java---SchemaExport----DDL 
2. 只有 DDL 
DDL---Middlegen---hbm----hbm2java----java 
3. 只有 Java 
java---XDoclet---hbm----SchemaExport----DDL 
从这里,大家也可以体会到 , Hibernate 强大的灵活性 

不过我们通常习惯专门的工具设计数据库,譬如 power designer 等工具,会自动生成 DDL ,
所以我们更需要通过 DDL ,就自动生成 Mapping file 和 java 类 

(2)在 Eclipse 开发工具中,有一个比较好用的插件 
Hibernate Synchronizer 
•  自动生成基本的 Hibernate 配置文件 
•  自动由表结构生成 POJO 类, XML Mapping 和基本的 DAO 类。 
•  精巧的继承结构将自动生成代码和用户定制的代码巧妙的分割开来。 
•  将自动生成的代码放在基类( Base* )中,将用户定制的代码放在子类中。分割了自动生成的代码和用户定制的代码。 
•  当表结构发生了变化时,插件只需要更改自己生成的基类,不用管用户定制的子类。用户定制的子类几乎不用改动,
   或只需要很少的改动即可适应新的表结构。

另:在 hibernate 使用一个 sessionFactory 操作多个数据库时候,可以使用

public StatelessSession openStatelessSession(Connection connection); 方法

 

 

转自http://www.aidengfeng.com/thread-23799-1-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值