Hibernate基本配置文件学习笔记

Hibernate的基本配置文件有两种:hibernate.cfg.xml和.hbm.xml文件。前者包含了Hibernate与数据库的基本连接信息,在Hibernate工作的初始阶段,这些信息被先后加载到Configuration和SessionFactory实例;后者包含了Hibernate的基本映射信息,即系统中每一个类与其对应的数据库表之间的关联信息,在Hibernate工作的初始阶段,这些信息通过hibernate.cfg.xml的mapping节点被加载到Configuration和SessionFactory实例。这两种文件信息包含了Hibernate的所有运行期参数。下面我们用详细的例子来说明这两种文件的基本结构和内容。
一、hibernate.cfg.xml文件:

<!--该文件的开头信息,对Hibernate而言,该类文件基本都这么开头:)--> 
 <?xml version='1.0' encoding='UTF-8'?> 
 <!DOCTYPE hibernate-configuration PUBLIC
 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 
<!-- 正文开始 --> 
 <hibernate-configuration> 
<!--下面是数据库的基本连接信息,对一个应用来说,设置一个session-factory节点就够了,除非我们中间使用了多个数据库--> 
 <session-factory> 
<!--用户名 --> 
 <property name="connection.username">root</property> 
<!--url信息 -->
<property name="connection.url">jdbc:mysql://localhost:3306/webases</property> 
<!--数据库方言信息-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property> 
<!--密码 -->
<property name="connection.password">274507</property> 
<!--数据库驱动信息 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property> 
<!--指定Hibernate映射文件路径 --> 
 <mapping resource="com/Hibernate/test_products.hbm.xml" /> 
 </session-factory> 
 </hibernate-configuration>


二、.hbm.xml文件:
由于Hibernate的关联关系包含了一对一、一对多、多对一和多对多等四种类型,因此,也就有分别与之对应的四种.hbm.xml文件。下面我们就以比较常用的双向“一对多”型关联关系为例,介绍一下.hbm.xml文件的基本结构和内容。有关Hibernate更详细的内容,请参考相关文资料。
该例中有两张数据库表:一张为“省”表,另一张为“市”表,所用的数据库为MySQL。二者的建表语句如下:

CREATE TABLE IF NOT EXISTS Province 
 (
 Guid INT NOT NULL AUTO_INCREMENT,
 Provincename VARCHAR(16) NOT NULL,
 PRIMARY KEY (Guid) 
 ) TYPE=InnoDB; 
 CREATE TABLE IF NOT EXISTS City 
 (
 Guid INT NOT NULL AUTO_INCREMENT,
 Cityname VARCHAR(32) NOT NULL,
 ProvinceID INTNOT NULL,
 PRIMARY KEY (Guid) 
 ) TYPE=InnoDB; 
 ALTER TABLE City ADD CONSTRAINT CityRFProvince FOREIGN KEY (ProvinceID) 
 REFERENCES Province (Guid) ON DELETE CASCADE ON UPDATE RESTRICT;


Province表为主控方,City表为被控方,两者之间存在双向的一对多的关系。表City通过外键ProvinceID与表Province进行关联:当表Province中有记录被删除时,表City中相关记录亦被删除;当表Province中有记录被保存或者更新时,表City中相关记录无任何变化。
将Hibernate自带工具Middlegen生成的Province.hbm.xml文件进行修改,内容如下:

<!--该文件的开头信息,对Hibernate而言,该类文件基本都这么开头:)--> 
 <?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"
 >
<!-- 映射文件开始 -->
 <hibernate-mapping>
<!-- 下面的class节点定义了Province类和对应数据库表之间的关联关系 -->
 <class
 name="com.xxx.hibernate.Province"
 table="Province"
 >
<!-- 下面的两个节点定义了Province类中的属性和该类对应数据库表中的字段之间的关联关系,其中Guid为对应数据库表的主键 --> 
 <id 
 name="guid" 
 type="int" 
 column="Guid" 
 > 
 <generator class="native" /> 
 </id> 
 <property 
 name="provincename" 
 type="java.lang.String" 
 column="Provincename" 
 not-null="true" 
 length="16"
 >
 </property>
<!-- 下面的set节点定义了Province类和City类之间的”一对多“型关联关系 -->
 <set 
 name="cities"<!-- 集合属性的名称 --> 
 lazy="true"<!-- 是否允许延迟加载 --> 
 inverse="true"<!-- 定义这个集合是否为双向关联关系中的方向一端 --> 
 cascade="delete"<!-- 定义有关操作是否关联到子实体(此处指City类对象) -->
 >
 <key>
 <column name="ProvinceID" /><!-- 定义集合所对应的数据库表的外键 -->
 </key>
 <one-to-many
 class="com.xxx.hibernate.City"<!-- 定义集合所属的类-->
 />
 </set>
 </class>
 </hibernate-mapping>

将Hibernate自带工具Middlegen生成的City.hbm.xml文件进行修改,内容如下:


<!--该文件的开头信息,对Hibernate而言,该类文件基本都这么开头:)-->
 <?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"
 >
<!-- 映射文件开始 -->
 <hibernate-mapping>
<!-- 下面的class节点定义了City类和对应数据库表之间的关联关系 -->
 <class
 name="com.xxx.hibernate.City"
 table="City"
 >
<!-- 下面的两个节点定义了City类中的属性和该类对应数据库表中的字段之间的关联关系,其中Guid为对应数据库表的主键-->
 <id 
 name="guid" 
 type="int" 
 column="Guid"
 >
 <generator class="native" />
 </id>
 <property 
 name="cityname" 
 type="java.lang.String" 
 column="Cityname" 
 not-null="true" 
 length="32"
 >
 </property>
<!-- 下面的many-to-one节点定义了Province类和City类之间的”一对多“型关联关系 -->
 <many-to-one
 name="province"<!-- 属性名称 -->
 class="com.xxx.hibernate.Province"<!-- 属性所属的类 --> 
 cascade="none"<!-- 指定哪些操作会从父对象(此处指City类对象)级联到子对象(此处指Province类对象) --> 
 outer-join="auto"<!-- 设置父子对象之间是否存在外连接 --> 
 not-null="true"<!-- 指定该属性是否一定为非空 -->
 >
 <column name="ProvinceID" /><!-- 定义父对象(此处指City类对象)所对应的数据库表的外键 -->
 </many-to-one>
 </class>
 </hibernate-mapping>

多对多的双向关联关系(中间表)

2007-06-06 17:26

在多对多的关联关系中,可拆分为两个一对多的关联关系,即在两个表中间增加一个关联表,记录这两个表之间的关联关系。若抛开关联表,则原2个表之间看不出任何的关系。

以为考试类别和考试科目为例,详细讲解在添加关联表的情况下两个表之间的hibernate设置。
考试类别表:exam_sort_enum
id:integer
name:string
考试科目表:subject
id:integer
name:string
考试类别科目关联表
exam_sort_enum_id:integer 对应考试类别表的id
subject_id:integer 对应考试科目表的id

ExamSortEnum.hbm.xml
<?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>
<class 
 name="model.ExamSortEnum" 
 table="EXAM_SORT_ENUM" 
 lazy="false" 
>
 <id
 name="id"
 type="integer"
 column="ID" 
 length="22"
 >
 <generator class="increment" />
 </id>

 <property
 name="name"
 type="string"
 column="NAME"
 length="255"
 />
 <set name="subject" table="EXAM_SORT_ENUM_SUBJECT" lazy="true" cascade="save-update">
 <key column="exam_sort_enum_id"/>
<many-to-many column="subject_id" class="model.Subject"/>
 </set> 
</class>
</hibernate-mapping>ExamSortEnum.java
package model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;public class ExamSortEnum implements Serializable{


private static final long serialVersionUID = <chmetcnv w:st="on" unitname="l" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1L</chmetcnv>;
private Integer id;
private String name;
private Set subject = new HashSet();

public ExamSortEnum(){}
public ExamSortEnum(Integer id){
 setId(id);
}

public void setSubject(Set subject){
 this.subject = subject;
}public Set getSubject(){
 return this.subject;
}

public Integer getId() {
 return id;
}public void setId(Integer id) {
 this.id = id;
}public String getName() {
 return name;
}public void setName(String name) {
 this.name = name;
}
}

关于映射文件:

映射文件要设置set,
name=subject 为ExamSortEnum.java文件中定义的Set对象,存储多个Subject类型的容器。
table="EXAM_SORT_ENUM_SUBJECT" 为对应的中间表的表名,由于两个业务表之间不能直接打交道,只能通过中间表来进行关联。
lazy="true" 延迟加载
cascade="save-update" 级联保存更新,若设置为all,delete,all-delete-orphans,则在删除一个ExamSortEnum对象时,关联的Subject对象也被删除,而此关联的subject对象可能被其他的为ExamSortEnum对象所引用。
<key column="exam_sort_enum_id"/> 指定中间表中参照为Exam_Sort_Enum表的外键为exam_sort_enum_id
<many-to-many>
column="subject_id" Exam_Sort_Enum表参照Subject表的外键为subject_id,即Exam_Sort_Enum表通过subject_id与Subject表关联
class="model.Subject" 指定set中name=subject中存放的是model.Subject对象。

Subject.hbm.xml
<?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>
<class 
 name="model.Subject" 
 table="SUBJECT" 
 lazy="false" 
>
 <id
 name="id"
 type="integer"
 column="ID" 
 length="22"
 >
 <generator class="increment" />
 </id>

 <property
 name="name"
 type="string"
 column="NAME"
 length="200"
 />

 <set name="examSortEnum" table="EXAM_SORT_ENUM_SUBJECT" lazy="true" inverse="true" cascade="save-update">
 <key column="subject_id"/>
<many-to-many column="exam_sort_enum_id" class="model.ExamSortEnum"/>
 </set>
</class>
</hibernate-mapping>Subject.java
package model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;public class Subject implements Serializable{

private static final long serialVersionUID = <chmetcnv w:st="on" unitname="l" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1L</chmetcnv>;
private Integer id;
private String name;
private Set examSortEnum = new HashSet();


public Subject(){}
public Subject(Integer id){
 setId(id);
}

public void setExamSortEnum(Set examSortEnum){
 this.examSortEnum = examSortEnum;
}
public Set getExamSortEnum(){
 return this.examSortEnum;
}public Integer getId() {
 return id;
}public void setId(Integer id) {
 this.id = id;
}public String getName() {
 return name;
}public void setName(String name) {
 this.name = name;
}
}

关于映射文件:
内容与ExamSortEnum.hbm.xml差不多,只是多了一个inverse="true",告诉hibernate控制权不在此处,两个映射文件只能设置一个。

测试类:

package model;import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;public class ExamSortEnumTest {
public static SessionFactory sf ;

static{
 try{
 Configuration cfg = new Configuration().configure();
 sf = cfg.buildSessionFactory();
 }catch(Exception e){
 e.printStackTrace();
 }
}

public void insert1(){
 Session sess = sf.openSession();
 Transaction tx = sess.beginTransaction();

 Subject sa = new Subject();
 sa.setName("A1");

 Subject sb = new Subject();
 sb.setName("B1"); Subject sc = new Subject();
 sc.setName("C1");

 ExamSortEnum esea = new ExamSortEnum();
 esea.setName("A");
 esea.getSubject().add(sa);
 esea.getSubject().add(sc);

 ExamSortEnum eseb = new ExamSortEnum();
 eseb.setName("B");
 eseb.getSubject().add(sb);
 eseb.getSubject().add(sc);

 sess.save(esea);
 sess.save(eseb);

 tx.commit();
 sess.close();

}

public static void main(String[] args){
 ExamSortEnumTest et = new ExamSortEnumTest();
 et.insert1();
}
}

执行后的结果:
考试类别表:exam_sort_enum
id name
<chmetcnv w:st="on" unitname="a" sourcevalue="3" hasspace="True" negative="False" numbertype="1" tcsc="0">3 A</chmetcnv>
4 B

考试科目表:subject
id name
<chmetcnv w:st="on" unitname="C" sourcevalue="3" hasspace="True" negative="False" numbertype="1" tcsc="0">3 C</chmetcnv>1
<chmetcnv w:st="on" unitname="a" sourcevalue="4" hasspace="True" negative="False" numbertype="1" tcsc="0">4 A</chmetcnv>1
5 B1

考试类别科目关联表
exam_sort_enum_id subject_id
3 3
3 4
4 3
4 5