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 的数据库,如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感兴趣的数据,在提取时只将这些数据映射为类的实例导出。
例如:
<
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();
}
}