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(); }}