Hibernate的对象关系映射(1)

    技术2022-05-11  96

    1. 映射文件

    hibernate-mapping-3.0.dtd,位于“/src/org/hibernate”下。

    2. 类映射

    2.1 抽象类映射 

    抽象类Container的定义如下:

    package  com.weportal.container; /** * @hibernate.class *         table = "CONTAINER" * @hibernate.discriminator  *         column = "CONTAINER_TYPE" *         type = "String" */ public   abstract   class  Container  {    private String containerId;    private double size;    private String name;    private String description;    /**     * @hibernate.id      *         generator-class = "hilo"     */    public String getContainerId() {        return containerId;    }         /**     * @hibernate.property      */    public String getName() {        return name;    }    /**     * @hibernate.property      */    public String getDescription() {        return description;    }    /**     * @param description The description to set.     */    public void setDescription(String description) {        this.description = description;    }        /**     * @param name The name to set.     */    public void setName(String name) {        this.name = name;    }    /**     * @return Returns the size.     * @hibernate.property      */    public double getSize() {        return size;    }    /**     * @param size The size to set.     */    public void setSize(double size) {        this.size = size;    }    /**     * @param containerId The containerId to set.     */    public void setContainerId(String containerId) {        this.containerId = containerId;    }}

    Box和Bottle类的定义如下:

    package  com.weportal.container; /** * @hibernate.subclass *         discriminator-values = "BOX"  */ public   class  Box  extends  Container  {    private double height;    private double length;    private double width;    /**     * @hibernate.property     */    public double getLength() {        return length;    }         /**     * @hibernate.property     */    public double getWidth() {        return width;    }        /**     * @hibernate.property     */    public double getHeight() {        return height;    }       /**     * @param height The height to set.     */    public void setHeight(double height) {        this.height = height;    }    /**     * @param length The length to set.     */    public void setLength(double length) {        this.length = length;    }    /**     * @param width The width to set.     */    public void setWidth(double width) {        this.width = width;    }}

     

    package com.weportal.container; /** * @hibernate.subclass  *         discriminator-values = "BOTTLE"  */ public   class  Bottle extends Container  {    private double diameter;    private double height;    /**     * @return Returns the diameter.     * @hibernate.property     */    public double getDiameter() {        return diameter;    }    /**     * @param diameter The diameter to set.     */    public void setDiameter(double diameter) {        this.diameter = diameter;    }    /**     * @return Returns the height.     * @hibernate.property     */    public double getHeight() {        return height;    }    /**     * @param height The height to set.     */    public void setHeight(double height) {        this.height = height;    }}

     映射文件Container.hbm.xml如下:

    Container类的主键id,生成主键所使用的generator是uuid,uuid是利用128位的UUID算法生成的字符串来作为主键。而native表示主键的生成由数据库底层去选择算法。

    <? xml version="1.0" ?> <! DOCTYPE hibernate-mapping PUBLIC    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > < hibernate-mapping  package ="com.weportal.container" >    < class  name ="Container" >        < id  name ="containerId"  type ="string" >            < generator  class ="uuid" ></ generator >        </ id >        < discriminator  column ="CONTAINER_TYPE" ></ discriminator >        < property  name ="size" ></ property >        < property  name ="name" ></ property >        < property  name ="description" ></ property >        < subclass  name ="Box"  discriminator-value ="BOX" >            < property  name ="height" ></ property >            < property  name ="length" ></ property >            < property  name ="width" ></ property >        </ subclass >        < subclass  name ="Bottle"  discriminator-value ="BOTTLE" >            < property  name ="diameter" ></ property >            < property  name ="height" ></ property >        </ subclass >    </ class > </ hibernate-mapping >

    使用下面的类来自动生成数据库表(so cool!),

    package com.weportal;import org.apache.log4j.PropertyConfigurator;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.hibernate.cfg.Environment; public   class  DatabaseGenerate  {    public static void main(String[] args) {        DatabaseGenerate idbg = new DatabaseGenerate();        idbg.generate(true);    }        public void generate(boolean create){        PropertyConfigurator.configure("log4j.Properties");        Configuration cfg = new Configuration();        cfg.configure();        if(create){            cfg.setProperty(Environment.HBM2DDL_AUTO, "create-drop");        }        SessionFactory sf = cfg.buildSessionFactory();    }}

    生成的表container的定义如下:

         create   table  `hibernate`.`container`(        `containerId`  varchar ( 255 default   ''   not   null ,       `CONTAINER_TYPE`  varchar ( 255 default   ''   not   null ,       `size`  double ,       `name`  varchar ( 255 ),       `description`  varchar ( 255 ),       `height`  double ,       `length`  double ,       `width`  double ,       `diameter`  double ,         primary   key  (`containerId`)    );     create   unique   index  ` PRIMARY on  `hibernate`.`container`(`containerId`);

    观察上表,container中既包含了Container中的属性,也包含了Box和Bottle两个之类中的属性,它们共享这个表。

     2.1.1 主键ID

    可以自定义一个org.hibernate.id.IdentifierGenerator接口的实现类作为主键ID的generator,例如下面的代码使用的是IP和当前的时间混合来作为ID。

    package  com.weportal.generator; import  java.io.Serializable; import  java.net.InetAddress; import  java.net.UnknownHostException; import  org.hibernate.HibernateException; import  org.hibernate.engine.SessionImplementor; import  org.hibernate.id.IdentifierGenerator; public   class  MyGenerator  implements  IdentifierGenerator  {    /* (non-Javadoc)     * @see org.hibernate.id.IdentifierGenerator#generate(org.hibernate.engine.SessionImplementor, java.lang.Object)     */    public Serializable generate(SessionImplementor session, Object obj)            throws HibernateException {        StringBuilder sb = new StringBuilder();        try {            sb.append(InetAddress.getLocalHost().getAddress().toString());        } catch (UnknownHostException e) {            e.printStackTrace();        }        sb.append(System.currentTimeMillis());        return sb.toString();    }    /* (non-Javadoc)     * @see org.hibernate.id.IdentifierGenerator#generate(org.hibernate.engine.SessionImplementor, java.lang.Object, java.lang.String)     */    public Serializable generate(SessionImplementor session, Object obj,            String entity) throws HibernateException {        StringBuilder sb = new StringBuilder();        try {            sb.append(InetAddress.getLocalHost().getAddress().toString());        } catch (UnknownHostException e) {            e.printStackTrace();        }        sb.append(System.currentTimeMillis());        return sb.toString();    }}

    利用MyGenerator代替Container中的“uuid”,

           < id  name ="containerId"  type ="string" >            < generator  class ="com.weportal.generator.MyGenerator" ></ generator >        </ id >

    hibernate自带的generator如下:

    generator算法说明foreign使用另外一个相关联的对象的标识符作为主键assigned主键由外部程序负责生成,在 save() 之前指定一个hilo通过hi/lo 算法实现的主键生成机制,需要额外的数据库表或字段提供高位值来源seqhilo与hilo 类似,通过hi/lo 算法实现的主键生成机制,需要数据库中的 Sequence,适用于支持 Sequence 的数据库,如Oracleincrement主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:不能在集群下使用identity采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL 中的主键生成机制sequence采用数据库提供的 sequence 机制生成主键。如 Oralce 中的Sequencenative由 Hibernate 根据使用的数据库自行判断采用 identity、hilo、sequence 其中一种作为主键生成方式uuid.hex由 Hibernate 基于128 位 UUID 算法 生成16 进制数值(编码后以长度32 的字符串表示)作为主键uuid.string

    与uuid.hex 类似,只是生成的主键未进行编码(长度16),不能应用在 PostgreSQL 数据库中

    2.1.2 where属性

    利用where属性可以选出hibernate感兴趣的数据,在提取时只将这些数据映射为类的实例导出。

    例如:

    < class  name = " Container "  where = " size < 1000 " >

    下面的代码检索出的结果是size < 1000 的记录。

    package  com.weportal.container; import  java.util.Iterator; import  java.util.List; import  org.apache.log4j.PropertyConfigurator; import  org.hibernate.Session; import  org.hibernate.SessionFactory; import  org.hibernate.cfg.Configuration; public   class  ContainerView  {    public static void main(String[] args) {        PropertyConfigurator.configure("log4j.Properties");        Configuration cfg = new Configuration();        cfg.configure();        SessionFactory sf = cfg.buildSessionFactory();        Session sess = sf.openSession();        List pcs = sess.createQuery("from Container").list();        if (pcs.isEmpty())            System.out.println("没数据");        for (Iterator it = pcs.iterator(); it.hasNext();) {            Container cter = (Container) it.next();            //System.out.println(cter.getClass().getName());            System.out.println("id : " + cter.getContainerId());            System.out.println("name : " + cter.getName());            System.out.println("size : " + cter.getSize());        }        sess.close();    }}

    最新回复(0)