1. 映射文件
hibernate-mapping-3.0.dtd,位于“/src/org/hibernate”下。
2. 类映射
2.1 抽象类映射
抽象类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类的定义如下:
/** */ /**
* @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;
}
}
/**/ /**
* @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表示主键的生成由数据库底层去选择算法。
<! 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!),
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的定义如下:
`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。
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”,
< generator class ="com.weportal.generator.MyGenerator" ></ generator >
</ id >
hibernate自带的generator如下:
generator | 算法说明 |
foreign | 使用另外一个相关联的对象的标识符作为主键 |
assigned | 主键由外部程序负责生成,在 save() 之前指定一个 |
hilo | 通过hi/lo 算法实现的主键生成机制,需要额外的数据库表或字段提供高位值来源 |
seqhilo | 与hilo 类似,通过hi/lo 算法实现的主键生成机制,需要数据库中的 Sequence,适用于支持 Sequence 的数据库,如Oracle |
increment | 主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:不能在集群下使用 |
identity | 采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL 中的主键生成机制 |
sequence | 采用数据库提供的 sequence 机制生成主键。如 Oralce 中的Sequence |
native | 由 Hibernate 根据使用的数据库自行判断采用 identity、hilo、sequence 其中一种作为主键生成方式 |
uuid.hex | 由 Hibernate 基于128 位 UUID 算法 生成16 进制数值(编码后以长度32 的字符串表示)作为主键 |
uuid.string | 与uuid.hex 类似,只是生成的主键未进行编码(长度16),不能应用在 PostgreSQL 数据库中 |
2.1.2 where属性
利用where属性可以选出hibernate感兴趣的数据,在提取时只将这些数据映射为类的实例导出。
例如:
下面的代码检索出的结果是size < 1000 的记录。
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();
}
}