hibernate设置派生属性, 在持久化类的访问方法中加入程序逻辑...

时间:2021-12-08 16:28:02
       假定Customer类有一个avgPrice属生, 表示这个客户的所有订单的平均价格. 它的取值为与它关联的所有Order对象的price的平均值. 在CUSTOMERS表中没有 avg_price字段. 可以在Customer类的setOrders()方法中加入程序逻辑来实现:
    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" />