private Set orders = new HashSet(0);
private double avgPrice;
public double getAvgPrice() {
return this.avgPrice;
}
private void setAvgPrice(double avgPrice) {
this.avgPrice = avgPrice;
}
public void setOrders(Set orders) {
this.orders = orders;
calculatePrice();
}
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++;
}
avgPrice = totalPrice/count;
setAvgPrice(avgPrice);
}
}
Customer類的getAvgPrice()方法爲public類型, 而setAvgPrice()方法爲private類型, 因此JAVA應用程序只能讀取avgPrice屬生, 但是不能直接修改avgPrice屬性. 當JAVA應用程序或者Hibernate調用setOrders()方法時, 會自動調用calculatePrice()方法, calculatePrice()方法又調用setAvgPrice()方法, 從而給avgPrice屬性賦值. 由此可見, 如果希望把爲持久屬性表示客戶的所有訂單的價格總和, 它的取值爲與Customer對象關聯的所有Order對象的price屬性值的和. 在CUSTOMERS表中沒有對應的TOTAL_PRICE字段.在Customer.xml文件中映射totalPrice屬性的代碼如下:
<property name="totalPrice" formula="(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID = ID)" />
當Hibernate從數據庫中查詢Customer對象時, 在select語句中會包含以上用於計算totalPrice派生屬性的子查詢語句:
select ID, NAME, SEX, 'CUSTOMER DESCRIPTION', (select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=1) from customers;
如果子查詢語句的查詢結果爲空, Hibernate會把totalPrice屬性賦值爲NULL, 如果totalPrice屬性爲double或int等基本類型, 會拋出異常:
[java] org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of 包名
爲了避免以上異常, 應該把totalPrice屬性定義爲Double或Integer等包裝類型.
<property>元素的formula屬性指定一個SQL表達式, 該表達式可以引用表的字段, 調用SQL函數或者包含子查詢語句. 例如LineItem類中有一個unitPrice屬性, 而在LINEITEMS表中沒有對應的UNIT_PRICE字段,可以通過以下方式映射unitPrice屬性:
<property name="unitPrice" formula="BASE_PRICE*QUANTITY" />