精通Hibernate:对象关系映射基础

开发 后端
本文通过三个方面介绍了对象关系映射基础,分别为持久化类的属性和访问方法、创建命名策略以及实例。详细请看下文。

 1、持久化类的属性和访问方法
(1)持久化类简介

 

在Hibernate中持久化类的访问方法有两个调用者,一个是Java应用程序,一个是Hibernate。值得注意的是,Java应用程序不能访问持久化类的private类型的getXXX()、setXXX(),而Hibernate没有这样的限制。

(2)基本类型属性和包装类型属性

Java有8种基本类型:byte,short,char,int,long,float,double,boolean;与之对应的Java提供了8种包装类型:Byte,Short,Character,Integer,Long,Float,Double,Boolean。基本类型与包装类型之间可以如下简单转换:

double prD=1;  
//把double基本类型转换成Double包装类型  
Double wrD=new Double(prD);  
//把Double包装类型转换成double基本类型  
prD=wrD.doubleValue(); 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

Hibernate两种类型都是支持的。

(3)在持久化类的访问方法中加入程序逻辑

(a)在Customer类的getName()和setName()方法中加入程序逻辑

假如在Customer类中有firstname属性和lastname属性,但是没有name属性,而数据库CUSTOMERS表中只有NAME字段。当Hibernate从数据库中取得了CUSTOMERS表的NAME字段值后,会调用setName()方法,此时应该让Hibernate通过setName()方法来自动设置firstname属性和lastname。故要在setName()方法中加入额外的程序逻辑。

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

在映射文件中此时直接映射name即可,无需映射firstname等。

<property name="name" column="NAME"
  • 1.

尽管在Customer类中没有定义name属性,由于Hibernate并不会直接访问name属性,而是通过getName()和setName()方法。只要在Customer.hbm.xml文件中映射了name属性,HQL语句就能访问:

Query query=seesion.createQuery("from Customer as c where c.name='Tom'"); 
  • 1.

但是如果把Customer.hbm.xml文件中name属性配置为:

<property name="name" column="NAME" access="field"
  • 1.

程序会直接去访问Customer实例中的name属性,就会出现异常。

(b)在Customer类的setOrders()方法中加入程序逻辑

假定Customer类中有一个avgPrice属性,表示订单的平均价格,取值为它所关联Order对象的price的平均值。在CUSTOMERS表中没有AVG_PRICE字段。可以如下操作:

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();  
 }  
 public Set getOrders(){  
   return orders;  
 }//定义为一个Set  
 private void calculatePrice(){  
     double avgPrice = 0.0;  
     double totalPrice = 0.0;  
     int count=0;  
/迭代计算orders里面所有price  
     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( new Double(avgPrice) );  
     }  
 } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

在Customer.hbm.xml文件不用映射avgPrice,因为Hibernate不会直接访问avgPrice属性,也不会调用getavgPrice()和setavgPrice().

 

(c)在Customer类的setSex()方法中加入数据验证逻辑

在持久化类的访问方法中,还可以加入数据验证逻辑。

public char getSex(){  
   return this.sex;  
 }  
 public void setSex(char sex){  
     if(sex!='F' && sex!='M'){  
       throw new IllegalArgumentException("Invalid Sex");  
     }  
     this.sex =sex ;  
 } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

(4)设置派生属性
持久化类并非所有属性都直接和表的字段匹配,持久化类的有些属性是可以在运行的时候得出的,这些称作派生属性。正如之前的avgPrice属性,该方案包括两个步骤:

  • 在映射文件中不映射avgPrice属性
  • 在Customer类的setOrders()方法中加入程序逻辑,自动为avgPrice属性赋值。

除了这种方法来设置派生属性,还可以如下解决:

利用<property>元素的formula属性。formula属性用来设置一个SQL表达式,Hibernate将根据它来计算派生属性的值。以Customer类的totalPrice属性为例:

<property name="totalPrice" formula="(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=ID)"/> 
  • 1.

在Hibernate从数据库中查询Customer对象时,若查询totalPrice,即:

select totalPrice from CUSTOMERS; 
  • 1.

使用formula属性后,上面的查询语句就会自动地被替代成:

select (select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=1) from CUSTOMERS; 
  • 1.

如果子句的查询结果为空,那么上述的语句就会出现异常。解决方法是:将totalPrice的属性定义为Double包装类型。

(5)控制insert和update语句

Hibernate在初始化阶段,就会根据映射文件的映射信息,为所有的持久化类定义以下的SQL语句。

以上SQL语句中的“?”代表JDBC PreparedStatement中的参数。这些SQL语句都存放在SessionFactory的内置缓存中,当执行Session的save()、update()、delete() 、load()和get()方法的时候,将从缓存中找到对应预定义的SQL语句,再把具体的参数值绑定到该SQL语句中。

#p#

2、创建命名策略

还有一直一种方法是实现Hibernate的org.hibernate.cfg.NamingStrategy接口,对于这个接口Hibernate提供了两种参考实现类:org.hibernate.cfg.defaultNamingStrategy和org.hibernate.cfg.ImprovedNamingStrategy类。

MyNamingStrategy.java

package mypack;  
import org.hibernate.cfg.ImprovedNamingStrategy;  
import org.hibernate.util.StringHelper;  
public class MyNamingStrategy extends ImprovedNamingStrategy {  
   public String classToTableName(String className) {  
        return  StringHelper.unqualify(className).toUpperCase()+'S';//classname转化成大写字母+S就是对应的表名  
   }  
   public String propertyToColumnName(String propertyName) {  
       return propertyName.toUpperCase();  
   }  
   public String tableName(String tableName) {  
       return tableName;  
   }  
   public String columnName(String columnName) {  
       return columnName;  
   }  
   public String propertyToTableName(String className, String propertyName) {  
       return classToTableName(className) + '_' +  
            propertyToColumnName(propertyName);  
   }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

 

 

 

使用命名策略后可以更好的将数据库中表名、列名对象化成类中的对象。

#p#

3、实例

本节的代码下载地址:http://down.51cto.com/data/326754

主要的BusinessService.java

package mypack;  
 
import org.hibernate.*;  
import org.hibernate.cfg.Configuration;  
import java.util.*;  
 
public class BusinessService{  
  public static SessionFactory sessionFactory;  
  static{  
     try{  
       Configuration config = new Configuration()  
             .setNamingStrategy( new MyNamingStrategy() )  
             .configure();       //加载hibernate.cfg.xml文件中配置的信息  
      sessionFactory = config.buildSessionFactory();  
    }catch(RuntimeException e){e.printStackTrace();throw e;}  
  }  
 
  public Customer loadCustomer(long customer_id){  
    Session session = sessionFactory.openSession();  
    Transaction tx = null;  
    try {  
      tx = session.beginTransaction();  
      Customer customer=(Customer)session.get(Customer.class,new Long(customer_id));  
      tx.commit();  
      return customer;  
    }catch (RuntimeException e) {  
      if (tx != null) {  
         tx.rollback();  
      }  
      throw e;  
    } finally {  
       session.close();  
    }  
  }  
 
  public void saveCustomer(Customer customer){  
    Session session = sessionFactory.openSession();  
    Transaction tx = null;  
    try {  
      tx = session.beginTransaction();  
      session.save(customer);  
      tx.commit();  
 
    }catch (RuntimeException e) {  
      if (tx != null) {  
         tx.rollback();  
      }  
      throw e;  
    } finally {  
       session.close();  
    }  
  }  
 
    public void loadAndUpdateCustomer(long customerId) {  
      Session session = sessionFactory.openSession();  
      Transaction tx = null;  
      try {  
        tx = session.beginTransaction();  
        Customer customer=(Customer)session.get(Customer.class,new Long(customerId));  
        customer.setDescription("A lovely customer!");  
        tx.commit();  
 
    }catch (RuntimeException e) {  
      if (tx != null) {  
        tx.rollback();  
      }  
      throw e;  
    } finally {  
      session.close();  
    }  
  }  
 
  public void updateCustomer(Customer customer){  
    Session session = sessionFactory.openSession();  
    Transaction tx = null;  
    try {  
      tx = session.beginTransaction();  
      session.update(customer);  
      tx.commit();  
 
    }catch (RuntimeException e) {  
      if (tx != null) {  
         tx.rollback();  
      }  
      throw e;  
    } finally {  
       session.close();  
    }  
  }  
 
  public void saveDictionary(Dictionary dictionary) {  
    Session session = sessionFactory.openSession();  
    Transaction tx = null;  
    try {  
      tx = session.beginTransaction();  
      session.save(dictionary);  
      tx.commit();  
 
    }catch (RuntimeException e) {  
      if (tx != null) {  
        tx.rollback();  
      }  
      throw e;  
    } finally {  
      session.close();  
    }  
  }  
 
 public void updateDictionary(Dictionary dictionary){  
    Session session = sessionFactory.openSession();  
    Transaction tx = null;  
    try {  
      tx = session.beginTransaction();  
      session.update(dictionary);  
      tx.commit();  
 
    }catch (RuntimeException e) {  
      if (tx != null) {  
        tx.rollback();  
      }  
      throw e;  
    } finally {  
      session.close();  
    }  
  }  
  public Dictionary loadDictionary(long dictionary_id) {  
    Session session = sessionFactory.openSession();  
    Transaction tx = null;  
    try {  
      tx = session.beginTransaction();  
      Dictionary dictionary=(Dictionary)session.get(Dictionary.class,new Long(dictionary_id));  
      tx.commit();  
      return dictionary;  
    }catch (RuntimeException e) {  
      if (tx != null) {  
        tx.rollback();  
      }  
      throw e;  
    } finally {  
      session.close();  
    }  
  }  
 
  public void 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());  
  }  
 
  public void printDictionary(Dictionary dictionary){  
      System.out.println("type:"+dictionary.getType());  
      System.out.println("key:"+dictionary.getKey());  
      System.out.println("value:"+dictionary.getValue());  
  }  
   public void test(){  
      Customer customer=new Customer("Laosan","Zhang",'M',new HashSet(),"A good citizen!");  
      Order order1=new Order("Order001",new Double(100),customer);  
      Order order2=new Order("Order002",new Double(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(1);  
      printCustomer(customer);  
 
      customer.setDescription("An honest customer!");  
      updateCustomer(customer);  
 
      loadAndUpdateCustomer(1);  
 
      Dictionary dictionary=new Dictionary("SEX","M","MALE");  
      saveDictionary(dictionary);  
 
      dictionary=loadDictionary(1);  
      dictionary.setValue("MAN");  
      updateDictionary(dictionary);  
 
      dictionary=loadDictionary(1);  
      printDictionary(dictionary);  
 
   }  
 
  public static void main(String args[]) {  
    new BusinessService().test();  
    sessionFactory.close();  
  }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.

原文链接:http://blog.csdn.net/yu422560654/article/details/7047661

【编辑推荐】

  1. 精通Hibernate:第一个Hibernate应用
  2. Hibernate缓存何时使用和如何使用
  3. Hibernate连接Mysql中文乱码处理
  4. Hibernate配置要点详谈
  5. Hibernate配置文件和映射元素解释
责任编辑:林师授 来源: yu422560654的博客
相关推荐

2009-09-23 13:26:10

Hibernate对象

2012-02-08 14:01:18

HibernateJava

2012-02-08 13:34:08

HibernateJava

2012-02-08 14:24:35

HibernateJava

2012-05-30 15:03:43

ibmdw

2009-09-25 12:59:52

Hibernate映射

2009-06-02 14:46:26

Hibernate关系映射教程

2009-06-18 14:22:06

Hibernate多对Hibernate

2012-05-10 09:44:39

MongoDBJava

2012-02-02 16:13:29

HibernateJava

2009-09-25 10:25:54

Hibernate缓存

2009-09-25 14:12:16

Hibernate继承

2021-09-03 15:27:17

鸿蒙HarmonyOS应用

2009-09-22 15:10:22

Hibernate映射

2009-09-23 17:34:18

Hibernate映射

2012-02-03 11:17:33

HibernateJava

2009-09-25 10:00:47

Hibernate映射

2012-02-03 10:07:04

HibernateJava

2009-09-21 17:33:50

Hibernate基础

2012-02-08 11:15:38

HibernateJava
点赞
收藏

51CTO技术栈公众号