Hibernate3高级特性-使用过滤器
Hibernate版本(hibernate-distribution-3.3.1.GA)
Hibernate3 新增了对某个类或集合使用预定义的过滤器条件 (filter criteria) 的功能。过滤器条件相当于定义一个非常类似于类和各种集合上的"where"属性的约束子句,但是过滤器条件可以带参数。应用程序可以在运行时决定是否启用给定的过滤器,以及使用什么样的参数值。过滤器的用法很像数据库视图,只还过是在应用程序员中确定使用什么样的参数。摘自--
http://docs.jboss.org/hibernate/core/3.6/reference/zh-CN/html/filters.html
一、在Hibernate中使用过滤器遵循以下步骤
- Define the filter within the mapping file of the targeted entity (identity the attributes to filter on,and their types)
- Apply the filter on the desired class or collection by indicating it with the <class> or <collection-type> tags
- After obtaining a session with which to perform your actions,enable the appropriate filter , setting any applicable parameters
二 使用 Hibernate3 过滤器
工程结构图(1)
在下面的两个例子中,不贴出 hibernate.cfg.xml和log4j.xml 两个配置文件的代码
example 1: Customer Class Filter Test
假设通过指定顾客的年龄作为查询条件,获取符合查询条件的顾客
1。Customer类文件,Customer 的属性分别是:年龄和姓名 并且每个Customer均有各自的id号
Customer.java
package com.laoyangx.chapter0; import java.io.Serializable; public class Customer implements Serializable { private static final long serialVersionUID = 9210200371341904932L; private Integer id; //顾客编号 private Integer age; //顾客年龄 private String name; //顾客姓名 public Customer() { } public Customer(Integer age, String name) { this.age = age; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2。 Hibernate的工具类
HibernateUtil.java
package com.laoyangx.chapter0; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; @SuppressWarnings({"rawtypes","unchecked"}) public class HibernateUtil { private static final SessionFactory sessionFactory; private static final ThreadLocal localSession = new ThreadLocal(); static { try{ sessionFactory = new Configuration().configure().buildSessionFactory(); }catch(HibernateException ex){ throw new RuntimeException("sessionFactory :" + ex.getMessage(), ex); } } public static Session currentSession() throws HibernateException { Session s = (Session) localSession.get(); if (s == null) { s = sessionFactory.openSession(); localSession.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = (Session) localSession.get(); localSession.set(null); if (s != null) s.close(); } }
3。Customer类的数据库映射文件,在配置文件增加了<filter-def>和<filter>两个元素,过滤条件是:顾客年龄大于25
chapter0_customer.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5 <hibernate-mapping>
6 <class name="com.laoyangx.chapter0.Customer" table="T_chapter0_customers" >
7 <id name="id" column="customer_id" type="java.lang.Integer">
8 <generator class="native"/>
9 </id>
10 <property name="age" column="customer_age" type="java.lang.Integer" />
11 <property name="name" column="customer_name" type="java.lang.String" length="25" />
12 <filter name="creationAgeFilter" condition="customer_age>:asOfAge" />
13 </class>
14 <filter-def name="creationAgeFilter">
15 <filter-param name="asOfAge" type="java.lang.Integer"/>
16 </filter-def>
17 </hibernate-mapping>
4。测试
TestFilterDef.java
package com.laoyangx.chapter0; import java.util.Iterator; import java.util.List; import junit.framework.TestCase; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; public class TestFilterDef extends TestCase { /** * 添加顾客 */ public void addCustomer(){ Session session=HibernateUtil.currentSession(); Transaction transaction=null; try { transaction=session.beginTransaction(); for(int i=20;i<30;i++){ session.save(new Customer(i,"customer"+i)); } transaction.commit(); } catch (HibernateException e) { if(transaction!=null) transaction.rollback(); e.printStackTrace(); } finally{ session.close(); } } /** * 通过指定顾客的年龄作为查询条件,获取顾客 */ public void getCustomerWithAge(){ Session session=HibernateUtil.currentSession(); Transaction transaciton=null; try { transaciton=session.beginTransaction(); session.enableFilter("creationAgeFilter").setParameter("asOfAge", new Integer(25)); //顾客年龄大于25 List resultSet=(List)session.createQuery("from Customer").list(); boolean resultNotEmpty=(resultSet!=null)&&resultSet.size()>0; if(resultNotEmpty){ for(Iterator iter=resultSet.iterator();iter.hasNext();){ Customer customer=(Customer)iter.next(); System.out.println("customer_id-> "+customer.getId()+" customer_name-> "+customer.getName() +" customer_age-> "+customer.getAge()); } } } catch (HibernateException e) { if(transaciton!=null) transaciton.rollback(); e.printStackTrace(); } finally{ session.close(); } } }
先运行 addCustomer()方法,向数据库中添加测试数据 运行之后,T_chapter0_customers表中的数据显示如下:
随后执行 getCustomerWithAge() 显示结果如下:
example 2: Customer Collection Filter
假设 Customer 与 Order 是一对多的关系 , 每个 Customer可以有多个 Order
1。Customer类文件,Customer 的属性分别是:年龄和姓名 并且每个Customer均有各自的id号。Order类文件 , Order 的属性分别是:日期、是否可见和订单编号。Customer 与 Order 二者之间通过 customer_order_id 进行关联。
Customer.java
package com.laoyangx.chapter0; import java.io.Serializable; import java.util.HashSet; import java.util.Set; public class Customer implements Serializable { private static final long serialVersionUID = 9210200371341904932L; private Integer id; //顾客编号 private Integer age; //顾客年龄 private String name; //顾客姓名 private Set<Order> orders=new HashSet<Order>(); public Customer() { } public Customer(Integer age, String name) { this.age = age; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } }
Order.java
package com.laoyangx.chapter0; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.Date; public class Order implements Serializable { private static final long serialVersionUID = 5266816497026247617L; private Integer id; //订单编号 private String date; //订单日期 private Boolean visible; //订单状态 private Customer customer; //订单来源 public Order() {} public Order(Date date, Customer customer,Boolean visible) { SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); this.date = sdf.format(date); this.customer = customer; this.visible=visible; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDate() { return date; } public void setDate(String date) { this.date =date; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Boolean getVisible() { return visible; } public void setVisible(Boolean visible) { this.visible = visible; } }
2。HibernateUtil工具类
HibbernateUitl.java 和 example1 中的 HibernateUitl.java 一样
3。Customer类的数据库映射文件,在配置文件增加 两个<filter-def>和<filter>,过滤条件是:订单的visible属性为true且顾客年龄大于25
chapter0_customer.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5 <hibernate-mapping>
6 <class name="com.laoyangx.chapter0.Customer" table="T_chapter0_customers" >
7 <id name="id" column="customer_id" type="java.lang.Integer">
8 <generator class="native"/>
9 </id>
10 <property name="age" column="customer_age" type="java.lang.Integer" />
11 <property name="name" column="customer_name" type="java.lang.String" length="25" />
12
13 <set name="orders" inverse="true" cascade="all">
14 <key column="customer_order_id" />
15 <one-to-many class="com.laoyangx.chapter0.Order"/>
16 <filter name="creationVisibleFilter" condition="order_visible=:asOfVisible" />
17 </set>
18 <filter name="creationAgeFilter" condition="customer_age>:asOfAge" />
19 </class>
20
21 <filter-def name="creationAgeFilter">
22 <filter-param name="asOfAge" type="java.lang.Integer"/>
23 </filter-def>
24
25 <filter-def name="creationVisibleFilter">
26 <filter-param name="asOfVisible" type="java.lang.Boolean"/>
27 </filter-def>
28
29 </hibernate-mapping>
chapter0_order.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5 <hibernate-mapping>
6 <class name="com.laoyangx.chapter0.Order" table="T_chapter0_orders" >
7 <id name="id" column="order_id" type="java.lang.Integer">
8 <generator class="native"/>
9 </id>
10 <property name="date" column="order_date" type="java.lang.String" length="10" />
11 <property name="visible" column="order_visible" type="java.lang.Boolean" />
12 <many-to-one name="customer" class="com.laoyangx.chapter0.Customer" column="customer_order_id"></many-to-one>
13 </class>
14 </hibernate-mapping>
5。测试
TestFilterDef.java
package com.laoyangx.chapter0; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Set; import junit.framework.TestCase; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; public class TestFilterDef extends TestCase { /** * 添加顾客和订单号,用于测试 */ public void fillData(){ Session session=HibernateUtil.currentSession(); Transaction transaction=null; try { transaction=session.beginTransaction(); for(int i=20;i<30;i++){ Customer customer=new Customer(i,"customer"+i); boolean visible=(0==i%2)?false:true; //当顾客的年龄为偶数是 visible=false 反之为 true Order order=new Order(new Date(),customer,visible); customer.getOrders().add(order); session.save(customer); } transaction.commit(); } catch (HibernateException e) { if(transaction!=null) transaction.rollback(); e.printStackTrace(); } finally{ session.close(); } } /** * 通过指定顾客的年龄作为查询条件,获取顾客 */ public void getCustomerWithAge(){ Session session=HibernateUtil.currentSession(); Transaction transaciton=null; try { transaciton=session.beginTransaction(); session.enableFilter("creationVisibleFilter").setParameter("asOfVisible",true); session.enableFilter("creationAgeFilter").setParameter("asOfAge", new Integer(25)); List resultSet=(List)session.createQuery("from Customer").list(); Boolean resultNotEmpty=(resultSet!=null)&&resultSet.size()>0; if(resultNotEmpty){ for(Iterator iter=resultSet.iterator();iter.hasNext();) { Customer customer=(Customer)iter.next(); Set<Order> orders=customer.getOrders(); Boolean orderIsNullOrEmpty=(orders!=null)&&orders.size()>0; if(orderIsNullOrEmpty){ System.out.println("customer_id-> "+customer.getId()+" customer_name-> "+customer.getName() +" customer_age-> "+customer.getAge()); for(Iterator<Order> i=orders.iterator();i.hasNext();){ Order order=(Order)i.next(); System.out.println("order_id-> "+order.getId()+" order_date-> "+order.getDate()); } } System.out.println("-----------------------------"); } } } catch (HibernateException e) { if(transaciton!=null) transaciton.rollback(); e.printStackTrace(); } finally{ session.close(); } } }
先运行 fillData()方法 ,向数据库中添加测试数据 运行之后 t_chapter0_customers和t_chapter0_orders这两张表中的数据如下:
order_visible 生成的规律是:顾客的年龄为偶数时候 order_visible=false 反之为true
运行 getCustomerWithAge() 方法 查询条件为顾客中年龄大于25且 order_visible为true(即顾客的年龄为奇数)