孙卫琴Hibernate第四章对象-关系映射基础

来源:互联网 发布:网络有利有弊 英语翻译 编辑:程序博客网 时间:2024/06/05 10:16
 
单个持久化类与单个数据库表之间进行映射的技巧:
主要解决以下问题:
       持久化类的属性没有相关的setXXX()和getXXX()方法;
持久化类的属性在数据库中没有对应的字段,或者数据库中的字段在持久化类中没有对应的属性;
控制Hibernate生成的insert和update语句;
设置从持久化类映射到数据库表,以及持久化类的属性映射到数据库表的字段的命名策略;
一.持久化类的属性及访问方法
 
1 、getXXX() setXXX() 的产生是为了控制属性的读权限和改权限;
2 、java中的基本类型和包装类型对应着相同的Hibernate映射类型;
3 、在持久化类中,java基本类型和包装类型比较:基本类型操作方便,可以直接进行运算,包装类不行;基本数据类型不能表达NULL值。(java包装类型与sql数据类型有更直接的对应关系)
二.Hibernate访问持久化类属性的策略
1.在对象--关系映射文件中,<property>元素的access属性用于指定访问持久化类的属性的方法。
      (1)property 默认值。表示Hibernate通过相应的setXXX() 和 getXXX()方法访问属性。
      (2)field 表明Hibernate运用java反射机制直接访问类的属性。(类中没有提供属性的setXXX() 和 getXXX()方法)
2. 在Customer类的setSex()方法中加入数据验证逻辑。
 
publicvoid setSex(char sex){
       if(sex!='F'&& sex!='M'){
           thrownew IllegalArgumentException("Invalid Sex");
       }
       this.sex=sex;
}
setSex(char sex)有两个调用者:java应用程序和Hibernate Java应用程序调用时,参数可能来自用户界面输入的数据,需要验证;而hibernate调用时,参数值来自数据库读出的数据,通常是合法的,不需要验证。解决这一个矛盾的方法是:
 把映射文件中的sex属性的<property>元素的access属性设为”field”
这样hinernate就会直接访问Customer实例的sex属性,而不调用setget方法
 
一个例子:
1 数据库部分:
dropdatabaseifexists SAMPLEDB;
createdatabase SAMPLEDB;
use SAMPLEDB;
 
createtable DICTIONARIES (
   ID bigintnotnull,
   TYPEvarchar(15),
   TYPE_KEY varchar(15),
   VALUEvarchar(128),
   primarykey (ID)
);
createtable ORDERS (
   ID bigintnotnull,
   ORDER_NUMBER varchar(15),
   PRICE doubleprecision,
   CUSTOMER_ID bigintnotnull,
   primarykey (ID)
);
createtable CUSTOMERS (
   ID bigintnotnull,
   NAMEvarchar(15),
   SEX char(1),
   `CUSTOMER DESCRIPTION` text,
   primarykey (id)
);
altertable ORDERS addindex IDX_CUSTOMER (CUSTOMER_ID), addconstraint FK_CUSTOMER foreignkey (CUSTOMER_ID) references CUSTOMERS (id);
 
注意: `CUSTOMER DESCRIPTION` sql引用标识符数据库中的字段含有空格)
2 java类:
 
Customer.java
 
package mypack;
 
import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
 
publicclass Customer implements Serializable {
 
    private Long id;
 
    private String firstName;
 
    private String lastName;
 
    privatecharsex;
 
    private Set orders = new HashSet();
 
    privatedoubleavgPrice;
 
    privatedoubletotalPrice;
 
    private String description;
 
    public Customer() {
       // TODO Auto-generated constructor stub
    }
 
    public Customer(String lastName, String firstName, char sex,
           HashSet orders, String description) {
       // TODO Auto-generated constructor stub
 
       this.lastName = lastName;
       this.firstName = firstName;
       this.sex = sex;
       this.orders = orders;
       this.description = description;
 
    }
 
    publicdouble getAvgPrice() {
       returnavgPrice;
    }
 
    public String getDescription() {
       returndescription;
    }
 
    publicvoid setDescription(String description) {
       this.description = description;
    }
 
    public String getFirstName() {
       returnfirstName;
    }
 
    public Long getId() {
       returnid;
    }
 
    publicvoid setId(Long id) {
       this.id = id;
    }
 
    public String getLastName() {
       returnlastName;
    }
 
    public Set getOrders() {
       returnorders;
    }
 
    publicvoid setOrders(Set orders) {
       this.orders = orders;
    }
 
    publicchar getSex() {
       returnsex;
    }
 
    publicvoid setSex(char sex) {
 
       if (sex != 'F' && sex != 'M') {
           thrownew IllegalArgumentException("Invalid Sex");
       }
       this.sex = sex;
    }
 
    publicdouble getTotalPrice() {
       returntotalPrice;
    }
 
    publicvoid setTotalPrice(double totalPrice) {
       this.totalPrice = totalPrice;
    }
 
    public String getName() {
       returnfirstName + " " + lastName;
    }
 
    publicvoid setName(String name) {
       StringTokenizer t = new StringTokenizer(name);
       firstName = t.nextToken();
       lastName = t.nextToken();
    }
 
    publicvoid caculatePrice() {
 
       double avgPrice = 0.0;
       double totalPrice = 0.0;
       int count = 0;
       Iterator it = getOrders().iterator();
       while (it.hasNext()) {
 
           Order order = (Order) it.next();
           totalPrice += order.getOrderPrice();
           count++;
       }
       avgPrice = totalPrice / count;
       setAvgPrice(avgPrice);
    }
 
    publicvoid setAvgPrice(double avgPrice) {
       this.avgPrice = avgPrice;
    }
}
 
Order.java 类
 
package mypack;
 
import java.io.Serializable;
 
publicclass Order implementsSerializable {
 
    private Long id;
 
    privatedoubleorderPrice;
 
    private String order_number;
 
    privatedoubleprice;
 
    private Customer customer;
 
    public Order(String order_number, double price, Customer customer) {
       // TODO Auto-generated constructor stub
       this.order_number = order_number;
       this.price = price;
       this.customer = customer;
    }
 
    public Customer getCustomer() {
       returncustomer;
    }
 
    publicvoid setCustomer(Customer customer) {
       this.customer = customer;
    }
 
    public String getOrder_number() {
       returnorder_number;
    }
 
    publicvoid setOrder_number(String order_number) {
       this.order_number = order_number;
    }
 
    publicdouble getPrice() {
       returnprice;
    }
 
    publicvoid setPrice(double price) {
       this.price = price;
    }
 
    publicdouble getOrderPrice() {
       returnorderPrice;
    }
 
    publicvoid setOrderPrice(double orderPrice) {
       this.orderPrice = orderPrice;
    }
 
    public Long getId() {
       returnid;
    }
 
    privatevoid setId(Long id) {
       this.id = id;
    }
}
 
Dictionary.java
 
package mypack;
 
import java.io.Serializable;
 
publicclass Dictionary implements Serializable {
 
    private Long id;
 
    private String type;
 
    private String type_key;
 
    private String value;
 
    public Dictionary() {
 
    }
 
    public Dictionary(String type, String type_key, String value) {
       this.type = type;
       this.type_key = type_key;
       this.value = value;
    }
 
    public Long getId() {
       returnid;
    }
 
    privatevoid setId(Long id) {
       this.id = id;
    }
 
    public String getType() {
       returntype;
    }
 
    publicvoid setType(String type) {
       this.type = type;
    }
 
    public String getType_key() {
       returntype_key;
    }
 
    publicvoid setType_key(String type_key) {
       this.type_key = type_key;
    }
 
    public String getValue() {
       returnvalue;
    }
 
    publicvoid setValue(String value) {
       this.value = value;
    }
}
 
3 映射文件部分
 
Customer.hbm.xml
 
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="mypack.Customer" table="customers"
       catalog="sampledb" dynamic-insert="true" dynamic-update="true"lazy= "false">
       <!-- dynamic-insert="true" dynamic-update="true"分别表示insert语句中仅包含所有取值不为空的字段只有字段发生变化时才会包含到update语句中-->
       <id name="id" type="long">
           <column name="ID" />
           <generator class="increment" />
       </id>
       <property name="name" type="string">
           <column name="NAME" />
       </property>
       <property name="sex" type="character" access="field"><!-- 直接取设属性值 -->
           <column name="SEX" length="1" />
       </property>
       <property name="description" type="text">
           <column name="`CUSTOMER DESCRIPTION`" />
 
       </property>
       <property name="totalPrice"
           formula="(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=ID)"> <!—数据库中不含有次字段,它对应一个sql语句的结果 -->
       </property>
       <set name="orders" inverse="true" cascade="save-update">
           <key column="CUSTOMER_ID"></key>
           <one-to-many class="mypack.Order" />
       </set>
 
    </class>
</hibernate-mapping>
 
Order.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="mypack.Order" table="ORDERS" catalog="sampledb" dynamic-insert="true" dynamic-update="true">
       <id name="id" type="long">
           <column name="ID" />
           <generator class="increment" />
       </id>
       <property name="order_number" >
       </property>
       <property name="price"></property>
       <many-to-one name="customer" column="CUSTOMER_ID"
           class="mypack.Customer">
       </many-to-one>
    </class>
</hibernate-mapping>
 
Dictionary.hbm.xml
 
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="mypack.Dictionary" table="DICTIONARIES"
       catalog="sampledb" mutable="false" lazy= "false"><!-- 整个实例不能被更新 -->
       <id name="id" type="long">
           <column name="ID" />
           <generator class="increment" />
       </id>
       <property name="type" type="string" access="field"></property>
       <property name="type_key" type="string" access="field"></property>
       <property name="value" type="string" access="field"></property>
    </class>
</hibernate-mapping>
4 测试类
 
package mypack;
 
import java.util.HashSet;
 
import org.hibernate.Session;
import org.hibernate.Transaction;
 
import sessionFactory.HibernateSessionFactory;
 
publicclass BusinessService {
 
    public Customer loadCustomer(Long customer_id) throws Exception {
       Session session = HibernateSessionFactory.getSession();
       Transaction tr = null;
 
       try {
 
           tr = session.beginTransaction();
           Customer customer = (Customer) session.load(Customer.class,
                  customer_id);
           tr.commit();
           return customer;
       } catch (Exception e) {
           // TODO: handle exception
           if (tr != null) {
              tr.rollback();
           }
           throw e;
       } finally {
           session.close();
       }
 
    }
 
    publicvoid saveCustomer(Customer customer) throws Exception {
       Session session = HibernateSessionFactory.getSession();
       Transaction tr = null;
       try {
           tr = session.beginTransaction();
           session.save(customer);
           tr.commit();
       } catch (Exception e) {
           // TODO: handle exception
           if (tr != null) {
              tr.rollback();
           }
           throw e;
       } finally {
           session.close();
       }
    }
 
    publicvoid loadAndUpdateCustomer(Long customerId) throws Exception {
       Session session = HibernateSessionFactory.getSession();
       Transaction tr = null;
       try {
           tr = session.beginTransaction();
           Customer customer = (Customer) session.load(Customer.class,
                  customerId);
           customer.setDescription("A lovely customer!");
           tr.commit();
       } catch (Exception e) {
           // TODO: handle exception
           if (tr != null) {
              tr.rollback();
           }
           throw e;
       } finally {
           session.close();
       }
 
    }
 
    publicvoid updateCustomer(Customer customer) throws Exception {
 
       Session session = HibernateSessionFactory.getSession();
       Transaction tr = null;
       try {
           tr = session.beginTransaction();
           session.update(customer);
           tr.commit();
       } catch (Exception e) {
           // TODO: handle exception
           if (tr != null) {
              tr.rollback();
           }
           throw e;
       } finally {
           session.close();
       }
    }
 
    publicvoid saveDictionary(Dictionary dictionary) throws Exception {
 
       Session session = HibernateSessionFactory.getSession();
       Transaction tr = null;
       try {
           tr = session.beginTransaction();
           session.save(dictionary);
           tr.commit();
       } catch (Exception e) {
           // TODO: handle exception
           if (tr != null) {
              tr.rollback();
           }
           throw e;
       } finally {
           session.close();
       }
    }
 
    publicvoid updateDictionary(Dictionary dictionary) throws Exception {
       Session session = HibernateSessionFactory.getSession();
       Transaction tr = null;
       try {
           tr = session.beginTransaction();
           session.update(dictionary);
           tr.commit();
       } catch (Exception e) {
           // TODO: handle exception
           if (tr != null) {
              tr.rollback();
           }
           throw e;
       } finally {
           session.close();
       }
    }
 
    public Dictionary loadDictionary(Long dictionary_id) throws Exception {
       Session session = HibernateSessionFactory.getSession();
       Transaction tr = null;
 
       try {
 
           tr = session.beginTransaction();
           Dictionary dictionary = (Dictionary) session.load(Dictionary.class,
                  dictionary_id);
           tr.commit();
           return dictionary;
       } catch (Exception e) {
           // TODO: handle exception
           if (tr != null) {
              tr.rollback();
           }
           throw e;
       } finally {
           session.close();
       }
    }
 
    publicvoid printCustomer(Customer customer) {
       System.out.println("name:" + customer.getName());
       System.out.println("sex:" + customer.getSex());
       System.out.println("description:" + customer.getDescription());
       System.out.println("avgPrice:" + customer.getAvgPrice());
       System.out.println("totalPrice:" + customer.getTotalPrice());
    }
 
    publicvoid printDictionary(Dictionary dictionary) {
       System.out.println("type:" + dictionary.getType());
       System.out.println("key:" + dictionary.getType_key());
       System.out.println("value:" + dictionary.getValue());
    }
 
    publicvoid test() throws Exception {
       // Customer customer = new Customer("Laosan", "Zhang", 'M', new
       // HashSet(),
       // "A good citizen!");
       // Order order1 = new Order("Order001", 100, customer);
       // Order order2 = new Order("Order002", 200, customer);
       // customer.getOrders().add(order1);
       // customer.getOrders().add(order2);
       //
       // saveCustomer(customer);
       //
       // customer = new Customer("Laowu", "Wang", 'M', new HashSet(), null);
       // saveCustomer(customer);
       //
       // customer = loadCustomer(new Long(1));
       //
       // customer.setDescription("An honest customer!");
       // updateCustomer(customer);
       //
       // printCustomer(customer);
       //    
       // loadAndUpdateCustomer(new Long(1));
 
       Dictionary dictionary = new Dictionary("SEX", "M", "MALE");
       saveDictionary(dictionary);
       printDictionary(dictionary);
 
       dictionary = loadDictionary(new Long(1));
       dictionary.setValue("MAN");
       updateDictionary(dictionary);
      
      
        dictionary = loadDictionary(new Long(1));
        printDictionary(dictionary);
 
    }
 
    publicstaticvoid main(String[] args) throws Exception {
 
       BusinessService b = new BusinessService();
       b.test();
    }
}
 
5 问题:
在测试 Customer 和 Dictionary的load 方法时报错:
could not initialize proxy - the owning Session was closed
 
解决办法:把对应类的映射文件中加入 lazy= "false" 限制(class元素中)
 
原创粉丝点击