NHibernate联合主键详细示例
使用NHibernate实现一对多,多对一的关联很是简单,可如果要用复合主键实现确实让人有些淡淡的疼。虽然很淡疼但还是要去抹平这个坑,在下不才,愿意尝试。
以示例进入正文,源码下载地址:
一、数据表关系图
很明显,他是一个自引用数表,实现无限级树结构的存储。
二、关键步骤
- 注解如何实现复合主键
根据官方文档说明,联合主键最好是一个独立的类,需要重载Equals和GetHashCode方法,且标记为可序列化。代码如下:
[Serializable]
public class BaseInfo
{
public virtual string Id { get; set; }
public virtual string GroupNumber { get; set; } public override bool Equals(object obj)
{
var baseInfo = obj as BaseInfo;
if (baseInfo == null)
{
return false;
} return baseInfo.Id == this.Id && baseInfo.GroupNumber == this.GroupNumber;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
- 子类配置好联合主键
[CompositeId(, Name = "BN")]
[KeyProperty(, Name = "Id", Column = "Id", TypeType = typeof(string))]
[KeyProperty(, Name = "GroupNumber", Column = "GroupNumber", TypeType = typeof(string))]
public virtual BaseInfo BN { get; set; }
说明:
1.实现为引用BaseInfo类,而不是继承.
- 实现一对 和 多对一的映射
这步没有多大难度,主要处理好注解的顺序即可,以及OneToMany时联合主键如何设置的问题.示例代码如下:
[Bag(, Name = "Childs", Cascade = "all", Lazy = CollectionLazy.False, Inverse = true)]
[Key()]
[Column(, Name = "ParentId")]
[Column(, Name = "GroupNumber")]
[OneToMany(, ClassType = typeof(Foo))]
public virtual IList<Foo> Childs { get; set; } [ManyToOne(, Name = "Parent", ClassType = typeof(Foo))]
[Column(, Name = "ParentId")]
[Column(, Name = "GroupNumber")]
public virtual Foo Parent { get; set; }
三、出错了,有Bug
- childs没有数据
重载的GetHashCode方法有问题,返回值应该是联合主键HashCode,优化后的实现如下:
public override int GetHashCode()
{
return (this.Id + "|" + this.GroupNumber).GetHashCode(); //判断缓存是否存在,已此作为Key
}
- 插入数据时报错,提示SqlParameterCollection的索引无效[索引溢出错误]
原因,最初在设计Parent的时候,与联合主键共用了一个字段GroupNumber,导致在NHibernate做映射转换的时候会多计算出一个需要填充的值,但SqlParameterCollection中又少一个位置。优化代码如下:
//外键与联合主键不要共用字段
[ManyToOne(, Name = "Parent", ClassType = typeof(Foo))]
[Column(, Name = "ParentId")]
[Column(, Name = "ParentGroupNumber")]
public virtual Foo Parent { get; set; }
说明:
1.由于联合外键与联合主键共用了一个字段,导致映射出错
四、终于实现了,总结
- 类都必须可以序列化,也就是要还serializable标注
- 继承BaseInfo实现联合主键(不推荐使用)
在Save时,如果用session.merge方法组合缓存与修改对象,返回值的主键会为Null
- 联合主键与联合外键字段不能重复,也不能共用
- 注意重载的GetHashCode和Equals方法
- GetHashCode返回实例的惟一标识
- Equals判断是否相同实例的具体实现
NHibernate联合主键详细示例的更多相关文章
- NHibernate composite-id联合主键配置
NHibernate的联合主键配置比较复杂,初次配置可能需要花些时间,但只要我们理解了,掌握一定的步骤还是很容易的. 1.设计数据结构 Users:用户表 名称 Users 说明 用户表 序号 字段名 ...
- NHibernate 映射基础(第三篇) 简单映射、联合主键
NHibernate 映射基础(第三篇) 简单映射.联合主键 NHibernate完全靠配置文件获取其所需的一切信息,其中映射文件,是其获取数据库与C#程序关系的所有信息来源. 一.简单映射 下面先来 ...
- Hibernate(5)—— 联合主键 、一对一关联关系映射(xml和注解) 和 领域驱动设计
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: One to One 映射关系 一对一单向外键(XML/Annotation) 一对一双向外键关联(XML/A ...
- SQL联合主键 查重
2014年最后一天,今天在给数据库导入数据的时候,遇到一个问题,就是联合主键去重. 事情是这样的,现有一个表M,我想找个表中导入了许多数据,并需要将字段A(int)和B(int)联合设置为主键. 但是 ...
- Hibernate注解映射联合主键的三种主要方式
今天在做项目的时候,一个中间表没有主键,所有在创建实体的时候也未加组件,结果报以下错误: org.springframework.beans.factory.BeanCreationException ...
- 联合主键用Hibernate注解映射的三种方式
第一.将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,再将该类注解为@Embeddable,最后在主类中(该类不包含联合主 ...
- EntityFramework中Mapper怎么定义联合主键?
HasKey(m => new { m.StoreId, m.CarTypeId, m.CarLevel}) 用“new {}”联合主键以“,”分隔形式定义
- SQL Server中的联合主键、聚集索引、非聚集索引、mysql 联合索引
我们都知道在一个表中当需要2列以上才能确定记录的唯一性的时候,就需要用到联合主键,当建立联合主键以后,在查询数据的时候性能就会有很大的提升,不过并不是对联合主键的任何列单独查询的时候性能都会提升,但我 ...
- sql,联合主键,按id分组求版本号最大值的集合
表结构如下: /* SQLyog v10.2 MySQL - 5.5.39 ************************************************************** ...
随机推荐
- 批处理中set截取字符具体解释
set截取字符具体解释 在批处理中,set的功能有点繁杂:设置变量.显示环境变量的名及值.做算术运算.等待用户的输入.字符串截取.替换字符串,是我们经常使用的命令之中的一个. 在字符串截取方面,新手 ...
- Strongly connected(hdu4635(强连通分量))
/* http://acm.hdu.edu.cn/showproblem.php?pid=4635 Strongly connected Time Limit: 2000/1000 MS (Java/ ...
- Ubuntu下安装Intel Fortran编译器(ifort)
Intel Fortan Compiler简称ifort, Windows下的ifort是收费的,但是Linux系统下提供免费的ifort,可以在下面的链接中下载需要的版本(必须先注册,随后会收到官网 ...
- HttpModule应用
由做网站操作日志想到的HttpModule应用 背景 在以前的Web项目中,记录用户操作日志,总是在方法里,加一行代码,记录此时用户操作类型与相关信息.该记录日志的方法对原来的业务操作侵入性较强, ...
- 从uibutton的点击谈谈ios的响应事件
最近在做一个项目,接连遇到两个关于点击事件的问题. 1.点击button不能响应事件的. 2.子view的frame超出了父view的容器大小,也不能响应点击事件. 效果图如右: 1.第一张图中的弹出 ...
- c# 即使服务又是可执行程序的代码实现
先看下代码 namespace UpdaterServer { class Program { static void Main(string[] args) { ) { ServiceBase[] ...
- CentOS 6下安装nodejs 0.9.0(转)
确保安装了python,大部分安装失败都是由于python版本过低导致.安装之前,升级python版本,升级步骤 http://www.tomtalk.net/wiki/Python. [root@S ...
- ASP.NET Web API是如何根据请求选择Action的?[下篇]
ASP.NET Web API是如何根据请求选择Action的?[下篇] 再<上篇>中我们简单介绍了用于实现Action选择机制的HttpActionSelector,接下来我们来讨论本章 ...
- jquery选择器之内容过滤选择器
先写出DOM元素的HTML结构: <style type="text/css"> /*高亮显示*/ .highlight{ background-color: gray ...
- JUnit java单元测试
首先须导入JUnit包:所在项目右击->Build Path->Add Libraries->选择JUnit->选择一个版本->Finish 一.手动生成 1.测试方法, ...