Hibernate二次笔记 之 从one-to-many分析处理技巧

这里用最常见的例子:Customer和Order来举例

客户和订单。

一个客户可能有N个订单,Customer和Order两个类分别对应两个表,字段中有各自相应属性...如Customer表里的id、name..Order表里的id,number,pricec_id..这些必要的属性外。当出现一种情况是业务需要某一用户的订单总金额(totalprice)和平均金额(avgprice)的时,该去怎么处理。

假设在Customer里面再加入两个字段的话,问题可以解决,但并不合理:因为数据在经常变动的情况下,双表关联频繁update显然会影响软件的性能,如果放在表中,这两个字段可视为是冗余数据

那么我们现在就不做一一对应的关系,只在类中有这两个属性,表中没有。利用已知的条件:每个order的金额、和用户的order数来在程序中求出总金额与平均金额;

有两种方法来处理这样的功能,一种通常的方法是在程序中写一处理方法:

import  java.io.Serializable;
import  java.util. * ;

public   class  Customer {

    
private  Long id;
    
private  String firstname;
    
private  String lastname;
    
private   char  sex;
    
private  Set orders  =   new  HashSet();
    
private   double  avgPrice;
    
private   double  totalPrice;
    
private  String description;

    
public  Customer() {
    }

    
public  Customer(String firstname, String lastname,  char  sex, Set orders,
                    String description) {
        
this .firstname  =  firstname;
        
this .lastname  =  lastname;
        
this .sex  =  sex;
        
this .orders  =  orders;
        
this .description  =  description;
    }

    
public  Long getId() {
        
return   this .id;
    }

    
public   void  setId(Long id) {
        
this .id  =  id;
    }

    
public  String getFirstname() {
        
return  firstname;
    }

    
public   void  setFirstname(String firstname) {
        
this .firstname  =  firstname;
    }

    
public  String getLastname() {
        
return  lastname;
    }

    
public   void  setLastname(String lastname) {
        
this .lastname  =  lastname;
    }

    
public  String getName() {
        
return  firstname  +   "   "   +  lastname;
    }

    
public   void  setName(String name) {
        StringTokenizer t 
=   new  StringTokenizer(name);
        firstname 
=  t.nextToken();
        lastname 
=  t.nextToken();
    }

    
public   double  getAvgPrice() {
        
return   this .avgPrice;
    }

    
private   void  setAvgPrice( double  avgPrice) {
        
this .avgPrice  =  avgPrice;
    }

    
public   double  getTotalPrice() {
        
return   this .totalPrice;
    }

    
private   void  setTotalPrice( double  totalPrice) {
        
this .totalPrice  =  totalPrice;
    }

    
public   void  setOrders(Set orders) {
        
this .orders  =  orders;
        calculatePrice(); 
// 或者通过 <property>的 formula 属性来实现
    }

    
public  Set getOrders() {
        
return  orders;
    }

    
private void  calculatePrice() {
        
double avgPrice = 0.0
;
        
double totalPrice = 0.0
;
        
int count = 0
;

        
if (getOrders() != null
) {
            Iterator iter 
=
 getOrders().iterator();
            
while
 (iter.hasNext()) {
                
double orderPrice =
 ((Order) iter.next()).getPrice();
                totalPrice 
+=
 orderPrice;
                count
++
;
            }
            
// Set the price for the order from the calcualted value

            avgPrice = totalPrice /  count;
            setAvgPrice(avgPrice);
        }
    }

    
public   char  getSex() {
        
return   this .sex;
    }

    
public   void  setSex( char  sex) {
        
if  (sex  !=   ' F '   &&  sex  !=   ' M ' ) {
            
throw   new  IllegalArgumentException( " Invalid Sex " );
        }
        
this .sex  =  sex;
    }

    
public  String getDescription() {
        
return   this .description;
    }

    
public   void  setDescription(String description) {
        
this .description  =  description;
    }

    
public   boolean  equals(Object lObj) {
        
if  ( this   ==  lObj) {
            
return   true // 比较的是两个对象的引用(references)是否相等
        }
        
if  (lObj  ==   null ) {
            
return   false // 检查 lObj是否为空
        }
        
if  (getClass()  !=  lObj.getClass()) {
            
return   false // 检查是否属于同一个class
        }
        
return   true ;
    }

}

可以看出,用calculatePrice()方法 来运算可以解决这样的问题的。

下面的一种方法是通过映射文件来解决此问题,如果从SQL语句上来讲,avgPrice和totalPrice分别都可以用SQL语句来查出。如下:

select  sum(o.PRICE)  from ORDERS  o where o.CUSTOMER_ID=?

select  avg(o.PRICE)  from ORDERS  o where o.CUSTOMER_ID=?

而hibernate的映射文件支持方程式formula,我们可以在Customer.hbm.xml里面这么写:

    ...
    
< property  name ="totalPrice"  
       formula
="(select  sum(o.PRICE)  from ORDERS  o where o.CUSTOMER_ID=ID)"   />
       
   
< property  name ="avgPrice"  
       formula
="(select  avg(o.PRICE)  from ORDERS  o where o.CUSTOMER_ID=ID)"   />
   
< property  name ="description"   type ="text"  column ="DESCRIPTION" />

再通过类里面的get、set方法来取得avgPrice和totalPrice。

 

总结,咋一看来,好像第二种方法比第一种方法要简练。但仔细想,现在我用的是SQL Server,如果底层数据库变了的话,而映射文件里的方程式恰好又有相关联的数据库函数的话,那么就违背了"write once,run anywhere"的原则,而第一种逻辑运算则变成了真理。除非没有了Java.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值