关于Struts2 + spring + hibernate进Q群: 130529143交流。
有偿技术支持Q群:398162181
1. One-to-One:
1.1按外键映射
One:
<hibernate-mappingpackage="com.lixuan.hibernate.one2one.foreign">
<classname="Manager"table="MANAGERS">
<idname="managerId"type="java.lang.Integer"access="field">
<columnname="MANAGER_ID"/>
<generatorclass="native"/>
</id>
<propertyname="managerName"type="java.lang.String"access="field">
<columnname="MANAGER_NAME"/>
</property>
<!-- 映射1-1映射的关联关系:在对应的数据表中已经有外键了,当前持久化类使用one-to-one进行映射 -->
<!--
没有外键的一端使用one-to-one元素,该元素使用property-ref属性指定使用被关联实体主键以外的字段作为关联字段
若不使用property-ref属性,则默认使用实体的主键作为关联字段;
-->
<one-to-onename="dept"class="Department"property-ref="manager"></one-to-one>
</class>
</hibernate-mapping>
One:
<hibernate-mappingpackage="com.lixuan.hibernate.one2one.foreign">
<classname="Department"table="DEPARTMENTS">
<idname="deptId"type="java.lang.Integer">
<columnname="DEPT_ID"/>
<generatorclass="native"/>
</id>
<propertyname="deptName"type="java.lang.String">
<columnname="DEPT_NAME"/>
</property>
<!-- 使用many-to-one的方式映射1-1关系映射 -->
<!--
这一列是外键:为many-to-one元素增加unique="true"属性来表示1-1关联
-->
<many-to-onename="manager"column="MANAGER_ID"unique="true"></many-to-one>
</class>
</hibernate-mapping>
1.2按主键映射
One:
<hibernate-mappingpackage="com.lixuan.hibernate.one2one.primary">
<classname="Manager"table="MANAGERS">
<idname="managerId"type="java.lang.Integer"access="field">
<columnname="MANAGER_ID"/>
<generatorclass="native"/>
</id>
<propertyname="managerName"type="java.lang.String"access="field">
<columnname="MANAGER_NAME"/>
</property>
<!-- 映射1-1映射的关联关系:在对应的数据表中已经有外键了,当前持久化类使用one-to-one进行映射 -->
<!--
没有外键的一端使用one-to-one元素,该元素使用property-ref属性指定使用被关联实体主键以外的字段作为关联字段;
-->
<one-to-onename="dept"class="Department"property-ref="manager"></one-to-one>
</class>
</hibernate-mapping>
One:
<hibernate-mappingpackage="com.lixuan.hibernate.one2one.primary">
<classname="Department"table="DEPARTMENTS">
<idname="deptId"type="java.lang.Integer">
<columnname="DEPT_ID"/>
<!-- 主键生成策略使用外键的方式生成主键-->
<generatorclass="foreign">
<paramname="property">manager</param>
</generator>
</id>
<propertyname="deptName"type="java.lang.String">
<columnname="DEPT_NAME"/>
</property>
<!--采用foreign主键生成策略的一端增加one-to-one元素映射关联属性,
one-to-one节点增加constrained="true,使当前主键添加外键约束 -->
<one-to-onename="manager"class="Manager"constrained="true"></one-to-one>
</class>
</hibernate-mapping>
2. One-to-Many:
2.1单向多对一:
Many:
<hibernate-mappingpackage="com.lixuan.hibernate.entities.n21">
<classname="Order"table="ORDERS">
<idname="orderId"type="java.lang.Integer">
<columnname="ORDER_ID"/>
<generatorclass="native"/>
</id>
<propertyname="orderName"type="java.lang.String">
<columnname="ORDER_NAME"/>
</property>
<!-- 映射多对一的关联关系。使用 many-to-one来映射多对一的关联关系 name:多这一端关联的一那一端的属性的名字 class:
一那一端的属性对应的类名 column:一那一端在多的一端对应的数据表中的外键的名字 -->
<many-to-onename="customer"class="Customer"column="CUSTOMER_ID"></many-to-one>
</class>
</hibernate-mapping>
One:
<hibernate-mappingpackage="com.lixuan.hibernate.entities.n21">
<classname="Customer"table="CUSTOMERS">
<idname="customerId"type="java.lang.Integer">
<columnname="CUSTOMER_ID"/>
<generatorclass="native"/>
</id>
<propertyname="customerName"type="java.lang.String">
<columnname="CUSTOMER_NAME"/>
</property>
</class>
</hibernate-mapping>
2.2双向一对多:
Many:
<hibernate-mappingpackage="com.lixuan.hibernate.entities.n21.both">
<classname="Order"table="ORDERS">
<idname="orderId"type="java.lang.Integer">
<columnname="ORDER_ID"/>
<generatorclass="native"/>
</id>
<propertyname="orderName"type="java.lang.String">
<columnname="ORDER_NAME"/>
</property>
<!--
映射多对一的关联关系。使用 many-to-one来映射多对一的关联关系
name:多这一端关联的一那一端的属性的名字
class:一那一端的属性对应的类名
column:一那一端在多的一端对应的数据表中的外键的名字
-->
<many-to-onename="customer"class="Customer"column="CUSTOMER_ID"></many-to-one>
</class>
</hibernate-mapping>
One:
<hibernate-mapping package="com.lixuan.hibernate.entities.n21.both">
<classname="Customer"table="CUSTOMERS">
<idname="customerId"type="java.lang.Integer">
<columnname="CUSTOMER_ID"/>
<generatorclass="native"/>
</id>
<propertyname="customerName"type="java.lang.String">
<columnname="CUSTOMER_NAME"/>
</property>
<!-- 映射一对多的那个集合属性-->
<!--
set:映射set类型的属性:
table:set中的元素对应的记录所在的数据库表名(该值需和多对一的多的那个表的名字保持一致);
inverse:指定由哪一方来维护关联关系,通常inverse="true":指定多的一端维护关联关系
cascade:设定级联操作,delete:级联删除;
1.cascade="delete-orphan"删除孤儿,与 1的一端 没有关联关系的 多的一端的对象。
2.cascade="save-update":保存 1的一端 时同时保存 多的一端
3.注意:开发时通常不设置此属性
order-by="ORDER_NAMEDESC":使用的是数据库表的列名
-->
<setname="orders"table="ORDERS"inverse="true"order-by="ORDER_NAME DESC">
<!-- 指定多的一端表中的外键列的名字:即ORDERS这个表中的哪列 -->
<keycolumn="CUSTOMER_ID"></key>
<!-- 指定映射类型 -->
<one-to-manyclass="Order"/>
</set>
</class>
</hibernate-mapping>
3. many-to-many:
3.1单向多对多:
3.2双向多对多:
Many: <hibernate-mappingpackage="com.lixuan.hibernate.n2n">
<classname="Category"table="CATEGORIES">
<idname="id"type="java.lang.Integer">
<columnname="ID"/>
<generatorclass="native"/>
</id>
<propertyname="name"type="java.lang.String">
<columnname="NAME"/>
</property>
<!-- table: 指定中间表名 -->
<setname="items"table="CATEGORIES_ITEMS">
<key>
<!-- 中间表的列名 -->
<columnname="C_ID"/>
</key>
<!-- 使用 many-to-many指定多对多的关联关系.
column指定Set集合中的持久化类在中间表的外键列的名称 -->
<many-to-manyclass="Item"column="I_ID"></many-to-many>
</set>
</class>
</hibernate-mapping>
Many:
<hibernate-mappingpackage="com.lixuan.hibernate.n2n">
<classname="Item"table="ITEMS">
<idname="id"type="java.lang.Integer">
<columnname="ID"/>
<generatorclass="native"/>
</id>
<propertyname="name"type="java.lang.String">
<columnname="NAME"/>
</property>
<!-- table: 指定中间表名 -->
<setname="categories"table="CATEGORIES_ITEMS"inverse="true">
<!-- 中间表的列名 -->
<keycolumn="I_ID"></key>
<!-- 使用 many-to-many指定多对多的关联关系.
column指定Set集合中的持久化类在中间表的外键列的名称 -->
<many-to-manyclass="Category"column="C_ID"></many-to-many>
</set>
</class>
</hibernate-mapping>
2. Hibernate主键生成策略
2.1 自然主键
(主键本身就是表中的一个字段,实体中一个具体的属性)表中已经具有某字段,并且该字段具有业务含义作为主键,称之为自然主键。
assigned(用户手动录入)
由Java程序负责生成标识符,Hibernate不管理主键,用户手动设置主键的值。如果不指定id元素的generator属性,则默认使用该主键生成策略
2.2 代理主键
(主键不是实体中某个具体的属性,而是一个不相关的字段)表中不具备业务含义的字段作为主键,称之为代理主键。更合理的方式是使用代理主键。
identity(主键自增)
适用于long、short或int类型主键,采用底层数据库本身提供的主键生成标识符。在DB2、MySQL、MS SQL Server、Sybase和HypersonicSQL数据库中可以使用该生成器,该生成器要求在数据库中把主键定义成为自增类型。Oracle没有自动增长
sequence(序列)
适用于long、short或int类型主键,Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence,MySQL这种不支持sequence
increment(主键自增,单线程,maxID+1)
适用于long、short或int类型主键,由Hibernate提供自动递增的方式生成唯一标识符,每次增量为1。只有当没有其他进程向同一张表中插入数据时才可以使用,不能再多线程环境下使用
hilo(主键自增,高低位算法)
hilo(高低位方式high low)是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值。保存hi值的表至少有一条记录(只与第一条记录有关),否则会出现错误。跨数据库,hilo算法生成的标志只能在一个数据库中保证唯一
native(hilo+identity+sequence三选一)
根据底层数据库对自动生成标识符的能力来选择i dentity、sequence、hilo三种生成器中的一种,适合跨数据库平台开发
uuid(随机字符串作主键)
Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,其UUID被编码为一个长度为32位的十六进制字符串。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字
uuid长度大,占用空间大,跨数据库,不用访问数据库就生成主键值,所以效率高且能保证唯一性,移植非常方便,推荐使用。
guid(全球唯一标识符)
全球唯一标识符,也称作 UUID,是一个128位长的数字,用16进制表示。算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成GUID。
Hibernate在维护主键时,先查询数据库,获得一个uuid字符串,该字符串就是主键值,该值唯一,缺点长度较大,支持数据库有限,优点同uuid,跨数据库,但是仍然需要访问数据库。注意:长度因数据库不同而不同。
需要数据库支持查询uuid,生成时需要查询数据库,效率没有uuid高,推荐使用uuid。