Hibernate.cfg.xml 配置文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- properties -->
<!-- jndi -->
<property name="connection.datasource">java:comp/env/jdbc/quickstart</property>
<property name="connection.provider_class">net.sf.hibernate.connection.DatasourceConnectionProvider</property>
<property name="dialect">net.sf.hibernate.dialect.SQLServerDialect</property>
<!-- jdbc
<property name="connection.url">jdbc:microsoft:sqlserver://localhost:1433;SelectMethod=cursor;DatabaseName=pubs</property>
<property name="connection.driver_class">com.microsoft.jdbc.sqlserver.SQLServerDriver</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
-->
<property name="jdbc.fetch_size">50</property><!-- 一次读的数据库记录数 -->
<property name="jdbc.batch_size">30</property><!-- 设定对数据库进行批量删除 -->
<property name="show_sql">true</property><!-- 将 Hibernate 发送给数据库的 sql 显示出来 -->
<!-- Mapping files -->
<mapping resource="cat.hbm.xml"/>
</session-factory>
</hibernate-configuration>
数据库表主键的知识点:
Generator 为每个 POJO 的实例提供唯一标识。一般情况,我们使用“ native ”。 class 表示采用由生成器接口 net.sf.hibernate.id.IdentifierGenerator 实现的某个实例,其中包括:
“ 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 数据库中。
“ foreign ”
使用另外一个相关联的对象的标识符作为主键。
以下举例:
1 、指定参数的情况:
<id name="id" unsaved-value="0">
<generator class="sequence">
<param name="sequence">SEQ_CHILD</param>
</generator>
</id>
使用的是 sequence ,适合 oracle 数据库;
2 、对于 sql server2000 中的数据库子增字段 , 在配置文件使用下列方法实现:
<id name="id" type="long" unsaved-value="0">
<column name="id" sql-type="numeric" not-null="true" />
<generator class="identity" />
</id>
这里主要是 :identity: 代表由 sql server2000 数据库自己提供子增字段 . 如果要 hibernate 自己提供 , 则用 increment 关键字来实现
3 、如果表中的主键用字符串类型 : 可以用 hibernate 自己提供的方法实现主键唯一 :
<id name="id" type="string" unsaved-value="null">
<column name="cid" sql-type="char(32)" not-null="true" />
<generator class="uuid.hex" />
</id>
使用的是 uuid.hex: 采用 128 位的算法来生成一个 32 位字符串。最通用的一种方式。适用于所有数据库。
重要的知识点 :
1. 如果有部门表 , 有员工表 , 员工表中有 dep_id, 则表部门类和员工类是 one-to-many 的关系 :
可以使用 : ( 在部门类 department 中使用下列 )
Department 类 :
/** 部门的所有员工 */
private Set staffs = new TreeSet();
xml 的文件 :
<set name="staffs" >
<key column="dep_id"/>
<one-to-many class="hbp.sys.data.Staff"/>
</set>
如果是 list, 需要用索引 <index> </index>, 具体其中的含义 , 不是很明白 . 待以后研究
2. 如果部门要有一个负责人 , 即部门表 (tb_department) 中有一个字段 :staff_id.
那么表示部门和负责人之间的关系是 many-to-one 的关系
Department 类 :
/** 部门负责人 id */
private Staff staff;
xml 文件
<many-to-one name="staff" class="hbp.sys.data.Staff" column="staff_id"/>
3. 多对多关系 , 一般我们是做一个中间关联表 . 我用角色和权限做了个例子 ,
Right(id,name) Role(id,name) 中间表 :tb_role_right(role_id,right_id)
Right 类中有一个 Role 的集合 :private Set roles=new TreeSet();
Role 类中也有一个 Right 的集合 :private Set rights=new TreeSet();
则两者是明显的多对多关系 . 使用 many-to-many 来实现 ;
xml 文件中
right.hbm.xml: 如下 :
<set name="roles" table="tb_role_right" cascade="all">
<key column="right_id"/>
<many-to-many column="role_id" class="hbp.sys.data.Role"/>
</set>
role.hbm.xml 文件中类似 :
<set name="rights" table="tb_role_right" cascade="all">
<key column="role_id"/>
<many-to-many column="right_id" class="hbp.sys.data.Right"/>
</set>
4. 几个值得注意的问题 :
a) 在 xml? 映射文件中 , 写类的名字时一定用类的全名 : 即 : 包 + 类名如 :(hbp.sys.data.Staff), 这个错误使我费了半天劲 .:(
b) 我在写实现基本 DAO 操作时 , 写了
session.delete("from Right as right where right.id="+id);
程序死活报错 , 我折腾了半天 , 跟踪到底 , 才恍然大悟 ,hibernate 在解析 sql 语句的时候把
其中的 right, 当成了数据库中的右连接 (" 保留字 "), 唉 , 这种关键字 , 不能随便用啊 ,:)
5. hibernate 中 HQL 语言的查询根据你的 sql 的不同而返回不同的对象类型 .
如果你使用 session.find(String hql)
一般会返回一个 List, 如 :from Staff staff; 返回的是包含所有的员工对象的集合
如你的 hql 为 :select count(*) from Staff staff; 则返回的是一个 Integer 对象
如果你使用的 hql 为 :select count(distinct staff.name),count(*) from Staff staff; 则返回的是一个 Object
即 Object[], 需要先把他转换成 Object[], 然后在取 [0],[1].
这种设计我不知道 hibernate 是如何处理的 , 感觉既好也不好 . 好的是可以使用一个 find 获得任意查询
不好在于根据 hql 来处理返回结果 , 容易出错 .