最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

ORM(ObjectRelational Mapper)---Hibernate对象映射

来源:动视网 责编:小OO 时间:2025-10-03 00:38:30
文档

ORM(ObjectRelational Mapper)---Hibernate对象映射

三、ORM(Object/RelationalMapper)---Hibernate对象映射一.                                                        ORM(Object/RelationalMapper)1.  OR映射---Hibernate基本数据类型Hibernate基本类型Java类型标准SQL字段类型booleanboolean,java.lang.BooleanBITyes_noboolean,java.lang.Bool
推荐度:
导读三、ORM(Object/RelationalMapper)---Hibernate对象映射一.                                                        ORM(Object/RelationalMapper)1.  OR映射---Hibernate基本数据类型Hibernate基本类型Java类型标准SQL字段类型booleanboolean,java.lang.BooleanBITyes_noboolean,java.lang.Bool
三、ORM(Object/Relational Mapper)---Hibernate对象映射 

一.                                                         ORM(Object/Relational Mapper)

1.   OR映射---Hibernate基本数据类型

Hibernate基本类型

Java类型

标准SQL字段类型

booleanboolean, java.lang.BooleanBIT
yes_noboolean, java.lang.BooleanCHAR(1) ( 'Y'/'N')
true_falseboolean, java.lang.Boolean CHAR(1) ( 'Y'/'N')
bytebyte, java.lang.ByteTINYINT
shortshort, java.lang.ShortSMALLINT
integerint, java.lang.IntegerINTEGER
longlong, java.lang.LongBIGINT
floatfloat, java.lang.FloatFLOAT
doubledouble, java.lang.DoubleDOUBLE
big_decimaljava.math.BigDecimalNUMBERIC
characterjava.lang.StringCHAR(1)
stringjava.lang.StringVARCHAR
datejava.util.Date, java.sql.DateDATE
timejava.util.Date, java.sql.TimeTIME
timestampjava.util.Date, java.sql.TimeStampTIMESTAMP
calendarjava.util.CalendarTIMESTAMP
calendar_datejava.util.CalendarDate
clobjava.sql.ClobCLOB
blobjava.sql.BlobBLOB
binarybyte[]VARBINARY, BLOB
textjava.lang.StringCLOB
seralizablejava.io.SerializableVARBINARY, BLOB
classjava.lang.ClassVARCHAR
localjava.util.LocaleVARCHAR
timezonejava.util.TimeZoneVARCHAR
currencyjava.util.CurrencyVARCHAR
2.   OR映射---实体映射示例

*.hbm.xml, 主体内容包含表/类映射, id映射, 属性字段映射三个部分.示例文件:

  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

    

        

    

    

 

XML文件头定义了文件的编码方式, DTD与Hibernate的版本有关, 上面是使用hibernate 3.x使用的DTD.

3.   OR映射---表/类映射

name: 指定了Java数据封装的POJO类类型.

table: 指定了数据库的表名

4.   OR映射---id映射

    

name: 指定了映射POJO类的属性名,

type: POJO类中属性的数据类型;

column: 数据库表的主键字段;

generator子元素:由其class属性指定主键生成方式:

∙assigned: 主键由应用程序产生, 不需要hibernate干预 

∙identity: 使用数据库的主键生成机制, 如MySQL, DB2、SQL Server的自增主键. 

∙sequence: 使用数据库的sequence机制, 如Oracle的sequence 

∙uuid.hex: 由Hibernate基于128位唯一值产生算法, 根据ip, 时间, jvm启动时间, 内部自增量生成十六进制的数值, 编码后成为一个32位长的字符串. 该方法提供了最好的数据库插入性能和数据库平台适应性. 

∙uuid.string: 与uuid.hex类似, 只是生成的主键没有进行编码, 只有16位长度. 在某些数据库可能出错. 

∙hilo: 通过hilo算法实现主键生成, 需要额外的数据库表保存主键生成历史状态. 

∙seqhilo: 与hilo类似, 只是主键历史状态保存在sequence中, 适用于支持sequence的数据库. 

∙increment: 主键按数值递增, 但如果多个实例同时访问同一个数据库, 各自生成主键,则容易造成主键重复. 

∙native: 由hibernate根据数据库适配器中的定义, 自动采用identity, hilo, sequence中的一种方式. 

∙foreign: 外部表的字段作主键. 

∙select: hibernate 3 中新增的.需要提供一个唯一的标识字段进行二次读取, 以获取触发器生成的主键值, 通过param子元素进行定义, 比如: 

 

    key_field

   该方法主要针对遗留系统的改造工程, 一些早期的系统主键依赖于触发器生成. 当数据库insert时, 触发器捕获这一操作, 并为主键赋值, 在插入数据库后, 再次读取某一识别字段读取已经插入的数据, 获取其主键值.

5.   OR映射---复合主键映射(composite-id)---实体属性组成主键

复合主键使用将取代id元素, 并具有property属性列表. 

     

     

   

复合主键的POJO类需要实现equals和hashcode方法, 可以使用apache commons lang包中的工具类实现(commons-lang.jar), 比如:

 

import org.apache.commons.lang.builder.EqualsBuilder;

import org.apache.commons.lang.builder.HashCodeBuilder;

import org.apache.commons.lang.builder.ToStringBuilder;

 

...

 

public String toString(){

    return new ToStringBuilder(this)

        .append("userid ", getUserid ())

        .append("when", getWhen ())

        .toString();

  }

 

  public boolean equals(Object other){

    if(!(other instanceof MyPoJoClass)){

       return false;

    }

    MyPoJoClass castOther=( MyPoJoClass)other; 

    return new EqualsBuilder()

        .appendSuper(super.equals(other))

        .append(this.getUserid (),castOther.getUserid() )

        .append(this.getWhen (),castOther.getWhen() )

        .isEquals();

  }

 

  public int hashCode(){

    return new HashCodeBuilder()

        .appendSuper(super.hashCode() )

        .append(getUserid ())

        .append(getWhen ())

        .toHashCode();

  }

装载复合主键的记录时, 考虑把类对应的对象的主键值填充好后作为load的第二个参数.

MyPoJoClass obj = new MyPoJoClass();

obj.setUserid(...);

obj.setWhen(...);

obj=(MyPoJoClass)session.load(MyPoJoClass.class, obj);

6.   OR映射---复合主键映射(composite-id)---基于主键类

可以用一个的类来描述主键, 示例:

     

     

   

此时, 需要定义一个新的类KeyClass来作为主键类, KeyClass实现equals和hashcode方法, 而在POJO中, 使用属性名keyClassProperty来表示主键, 其类类型为KeyClass.

7.   OR映射---composite-id其他子节点

composite-id除了key-property子节点外, 还具有可选子节点.完整的节点内容:

class="ClassName" 

unsaved-value="any|none" >

 

      name=" propertyName "

type="type_name" />

...

        name=" propertyName " />

...

   

8.   OR映射---属性/字段映射

name: POJO类的属性名,

type: POJO类中属性的数据类型; 如果是字符串,可以省略

column: 数据库中的字段名. 如果和属性同名, 可以省略.

9.   OR映射---自定义数据类型 UserType, CompositeUserType接口

hibernate3 中的为: org.hibernate.usertype(hibernate2中为net.sf包)下面的两个接口: UserType 和 CompositeUserType . 它们提供自定义类型的规范, 这里以UserType为例.

package org.hibernate.usertype;

 

import java.io.Serializable;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

 

import org.hibernate.HibernateException;

 

public interface UserType {

 

     /**

* 返回本类型所映射的SQL类型, 返回的是int[]数组. 可以取java.sql.Types中的int静态常量. 

* 比如有: public final static int DOUBLE  =   8;

      */

     public int[] sqlTypes();

 

     /**

      * 定义本类型的nullSafeGet() 方法返回的数据的类型

      */

     public Class returnedClass();

 

     /**

* 定义两个数据的比较方法, 返回true表示相等, false表示不等.

      */

     public boolean equals(Object x, Object y) throws HibernateException;

 

     /**

      * Get a hashcode for the instance, consistent with persistence "equality"

      */

     public int hashCode(Object x) throws HibernateException;

 

     /**

      * 定义从ResultSet中读取数据并转换成自定义类型的方法, 对数据库null应该考虑

    * 参数names 包含了当前自定义类型的映射字段名称

      */

public Object nullSafeGet(ResultSet rs, String[] names, Object owner)  

throws HibernateException, SQLException;

 

     /**

      * Hibernate进行数据保存时被调用的方法

      * @param st a JDBC prepared statement

      * @param value the object to write, 类型应该是returnedClass()方法返回的Class指定的类型

      * @param index statement parameter index

      * @throws HibernateException

      * @throws SQLException

      */

     public void nullSafeSet(PreparedStatement st, Object value, int index) 

throws HibernateException, SQLException;

     /**

      * 自定义的对象复制方法, 用作构造返回对象. 

    * nullSafeGet方法被调用后, Hibernate获得了自定义数据对象, 

* 这个对象成为数据库读出的原始对象, 通过deepCopy方法, Hibernate

* 返回一个复本给用户. 脏数据检查时, 如果两个对象不等(equals方法返回false),

* 就会执行数据库持久化操作.

      * @param value the object to be cloned, which may be null

      * @return Object a copy

      */

     public Object deepCopy(Object value) throws HibernateException;

 

     /**

      * Are objects of this type mutable?

      * 本类型实例是否可变

      * @return boolean

      */

     public boolean isMutable();

 

     /**

* 把对象转化为二级缓存中保存. 经常把当前对象对其他对象的引用, 保存为其id值.

      * Transform the object into its cacheable representation. At the very least this

      * method should perform a deep copy if the type is mutable. That may not be enough

      * for some implementations, however; for example, associations must be cached as

      * identifier values. (optional operation)

      *

      * @param value the object to be cached

      * @return a cachable representation of the object

      * @throws HibernateException

      */

     public Serializable disassemble(Object value) throws HibernateException;

 

     /**

    * 把二级缓存中获取的数据转换为自定义的对象数据

      * Reconstruct an object from the cacheable representation. At the very least this

      * method should perform a deep copy if the type is mutable. (optional operation)

      *

      * @param cached the object to be cached

      * @param owner the owner of the cached object

      * @return a reconstructed object from the cachable representation

      * @throws HibernateException

      */

     public Object assemble(Serializable cached, Object owner) throws HibernateException;

 

     /**

      * During merge, replace the existing (target) value in the entity we are merging to

      * with a new (original) value from the detached entity we are merging. For immutable

      * objects, or null values, it is safe to simply return the first parameter. For

      * mutable objects, it is safe to return a copy of the first parameter. For objects

      * with component values, it might make sense to recursively replace component values.

      *

      * @param original the value from the detached entity being merged

      * @param target the value in the managed entity

      * @return the value to be merged

      */

     public Object  replace(Object original, Object target, Object owner)

 throws HibernateException;

}

 

如果一个用户具有多个email, 可以分别定义多个字段保存, 也可以定义一个子表专门保存, 但都有点大动干戈. 可以考虑用一个字符串字段保存, 相邻的email用一个;隔开. 比如:

package cn.thinkmore.hibernate.pojo;

 

import java.io.Serializable;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Types;

import java.util.*;

 

import org.hibernate.Hibernate;

import org.hibernate.HibernateException;

import org.hibernate.usertype.UserType;

 

public class EmailList implements UserType {

 

     private static final String SPLITTER = ";";

 

     private static final int[] TYPES = new int[] { Types.VARCHAR };

 

     public Object assemble(Serializable cached, Object owner)

                   throws HibernateException {

            return null;

     }

 

     public Object deepCopy(Object value) throws HibernateException {

            if (!(value instanceof List)) {

                   return null;

            }

            List src = (List) value;

            List tar = new ArrayList();

            tar.addAll(src);

            return tar;

     }

 

     public Serializable disassemble(Object value) throws HibernateException {

            return null;

     }

 

     public boolean equals(Object x, Object y) throws HibernateException {

            if (x == y)

                   return true;

            if (x != null && y != null) {

                   List xList = (List) x;

                   List yList = (List) y;

                   if (xList.size() != yList.size())

                          return false;

                   for (int i = 0; i < xList.size(); i++) {

                          String strX = xList.get(i).toString();

                          String strY = yList.get(i).toString();

                          if (!strX.equals(strY))

                                 return false;

                   }

            }

            return false;

     }

 

     

     public boolean isMutable() {

            return false;

     }

 

     public Object nullSafeGet(ResultSet rs, String[] names, Object owner)

                   throws HibernateException, SQLException {

            String value = Hibernate.STRING.nullSafeGet(rs, names[0]).toString();

            if(null!=value)

                   return parse(value);

            return null;

     }

 

     private List parse(String value) {

        String[] strs = org.apache.commons.lang.StringUtils.split(value,SPLITTER);

            List emails = new ArrayList();

            for(int i=0; i                   emails.add(strs[i]);

            }

        return emails;

     }

     

     private String assemble(List list) {

            StringBuilder sb = new StringBuilder();

            int maxIndex = list.size()-1;

            for(int i=0; i                   sb.append(list.get(i)).append(SPLITTER);

            }

            if(0<=maxIndex){

                   sb.append(list.get(maxIndex));

            }

            return sb.toString();

     }

     

     public void nullSafeSet(PreparedStatement st, Object value, int index)

                   throws HibernateException, SQLException {

         if(null!=value&&(value instanceof List)){

                String str = assemble((List)value);

                Hibernate.STRING.nullSafeSet(st,str,index);

         }else if(null!=value){

                Hibernate.STRING.nullSafeSet(st,value.toString(), index);

         }else{

                Hibernate.STRING.nullSafeSet(st,null, index);

         }

     }

 

     public Object replace(Object original, Object target, Object owner)

                   throws HibernateException {

            return null;

     }

 

     public Class returnedClass() {

            return List.class;

     }

 

     public int[] sqlTypes() {

            return TYPES;

     }

 

     public int hashCode(Object x) throws HibernateException {

            return 0;

     }

}

数据关联关系

数据关联关系在实体的子类里面不会被自动继承.

10. 一对一关联 ----- 主键关联 one-to-one

一对一的主键关联, 指两个表的记录是一对一的关系, 且一个表的主键取为另一个表对应的记录的主键.

   

            

          

      

      

      

      

      

                           class="cn.thinkmore.hibernate.pojo.Gene" />

   

 

name: 属性名

class: java全路径类名

cascade: 是否级连操作, all , none

outer-join: 是否外链接, true/false

   

           

          

             citizen

          

      

      

      

      

                          class="cn.thinkmore.hibernate.pojo.Citizen" />

   

 

Constrained: 次关联中的约束方.

.....

Session s = HibernateSession3.getSession();      

       Citizen one = new Citizen();

       one.setIdcard("1234567012345678");

       one.setName("Mike");

       one.setSex("M");

       Gene gene = new Gene();

       gene.setBloodType("AB");

       gene.setDna("Ajodjjd[[joa");

       gene.setSpecial("White");

 

       one.setGene(gene);

       gene.setCitizen(one);

 

       Transaction trans = s.beginTransaction();

       s.saveOrUpdate(one);

       trans.commit();

 

       // 两条数据一起被保存, 查询时也会关联查出来.

       Query query = s.createQuery("From  Citizen");

       List list = query.list();

       for (int i = 0; i < list.size(); i++) {

           one = (Citizen) list.get(i);

           if (null == one)

              continue;

           gene = (Gene) one.getGene();

           if (null != gene){

            System.out.println(gene.getId()+":"+gene.getSpecial()+":"+gene.getDna());

           }

}

11. 单向一对多关联 ----- 唯一外键关联 one-to-many

 

一个用户可以多个email:

 

   

 

12. 双向一对多关联

 

除了在主控方配置一对多, 还要在被控方配置对应的多对一关系:

 

User:

   

 

Email:

 

再有例子:一个职员(是人的子类)前后可能有多条工作(每次工作是一条记录):

   

       Users may bid for or sell auction items.

           

          

        

      

        

                   

      

       

                            cascade="all" 

                     class="webapp.hibernate.pojo.Gene"/>             

      

 

   

           

          

        

      

        

                   

      

                           cascade="all" 

                     class="webapp.hibernate.pojo.Gene"/>   

                     

      

           

              

                        

      

 

   

           

          

        

 

      

                   

      

              

      

public static void testOne2Many() {

       Session s = HibernateSession3.getSession();

       Employee e = new Employee();

       e.setName("一对多");

       e.setIdcard("1234567012345678");

       e.setBirth(new java.sql.Date(System.currentTimeMillis()-24L*3600*1000*365*25));

       

       JobList job1 = new JobList();

       job1.setEmployee(e);

       job1.setCompany("A gongsi");

       job1.setBegin(new java.sql.Date(System.currentTimeMillis()-24L*3600*1000*365*5));

       job1.setEnd(new java.sql.Date(System.currentTimeMillis()-24L*3600*1000*365*4));

       

       JobList job2 = new JobList();

       job2.setEmployee(e);

       job2.setCompany("B gongsi");

       job2.setBegin(new java.sql.Date(System.currentTimeMillis()-24L*3600*1000*365*4));

       job2.setEnd(new java.sql.Date(System.currentTimeMillis()-24L*3600*1000*365*2));

       

       Set jobs = new HashSet();

       jobs.add(job1);

       jobs.add(job2);

       e.setJobs(jobs);

       

 

       Transaction trans = s.beginTransaction();

       // 两个表的数据一起被保存, 查询时也会关联查出来.

       s.saveOrUpdate(e);

       trans.commit();

 

 

       Query query = s.createQuery("From Employee");

       List list = query.list();

       for (int i = 0; i < list.size(); i++) {

           Employee one = (Employee) list.get(i);

           if (null == one)

              continue;

           System.out.println(one.getName()+":"+one.getBirth()+":");

           Set joblist = one.getJobs();

           for(Object o:joblist){          

              JobList j = (JobList)o;

              System.out.println("\工作:"+j.getCompany()+":"+j.getBegin()+":"+j.getEnd());

           }

           System.out.println("---------------------------------------");

       }

 

    }

 

13. 双向多对多关联

一个用户可以在银行有多个帐号

User:

   

           

          

        

      

        

                   

      

       

                            cascade="all" 

                     class="webapp.hibernate.pojo.Gene"/>

        

           

             

        

      

 

Bank:

       Users may bid for or sell auction items.

           

          

        

          

                  

      

       

           

             

        

      

 

    public static void testMany2Many() {

       Session s = HibernateSession3.getSession();

       Iterator itor =(Iterator)s.createQuery("FROM MoneyUser").iterate();

       while(itor.hasNext()){

           MoneyUser moneyUser =  itor.next();

           Set banks = moneyUser.getBanks();

           Iterator bankItor = banks.iterator();

           while(bankItor.hasNext()){

              Bank bank = bankItor.next();

              System.out.println(moneyUser.getName()+"  "+bank.getBankname());

           }

       }

    }

    

    public static void testMany2Many2() {

       Session s = HibernateSession3.getSession();

       Iterator itor = s.createQuery("FROM Bank").iterate();

       while(itor.hasNext()){

           Bank bank =  itor.next();

           Set customers = bank.getCutomers();

           Iterator customerItor = customers.iterator();

           while(customerItor.hasNext()){

              MoneyUser moneyUser = customerItor.next();

              System.out.println(bank.getBankname()+"  "+moneyUser.getName());

           }

       }

    }

文档

ORM(ObjectRelational Mapper)---Hibernate对象映射

三、ORM(Object/RelationalMapper)---Hibernate对象映射一.                                                        ORM(Object/RelationalMapper)1.  OR映射---Hibernate基本数据类型Hibernate基本类型Java类型标准SQL字段类型booleanboolean,java.lang.BooleanBITyes_noboolean,java.lang.Bool
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top