当我在学习使用NHibernate Mapping Attribute的时候,遇到复合主键映射问题,查询了很多资料,也向朋友请教过,由于相关资料不多,中间走了些弯路,好在最终较好解决了,现记录分享如下:

一、环境:vs2019,

问题一:

因为ISession().Get<T>(object)方法,只有一个参数,当我们使用这个方法的时候,因为映射的数据表主键是复合主键,应该是多个参数;有时候我们可能觉得,这样做不是必要的,因为我们可以使用很多其他的NHibernate所支持的Query方法,但是我们有几个问题需要考虑,我们的代码可能给其他同事修改,我们要保证代码完整性,确保ISession().Get<T>(object)方法能使用,还有如果我们把NHibernate执行的sql语句显示出来会发现其他query方法跟ISession().Get<T>(object)方法是不一样的,还有我们获取实体对象的一般方法都是通过主键,等等原因吧,这时候这样做的必要性就体现出来了;

解决办法:

1)、定义复核主键类;

2)、此类中有且只有所有的主键字段属性

3)、重写Equals()和GetHashCode()两个方法;

4)、复核主键类必须可序列化,也就是需要[Serializable]特性;

5)、使用NHibernate Mapping Attribute的特性映射所有属性;

[Serializable]
public class PaiVisitEmpPK
{[CompositeId(0, Name = "ID", ClassType = typeof(PaiVisitEmpPK))][KeyProperty(1, TypeType = typeof(string), Column = "SERIALNO", Name = "Serialno")][KeyProperty(2, TypeType = typeof(short), Column = "ROWNO", Name = "Rowno")]public virtual string Serialno { get; set; }public virtual short Rowno { get; set; }public override int GetHashCode() => (Serialno + "|" + Rowno).GetHashCode();public override bool Equals(object obj){if (typeof(PaiVisitEmpPK) != obj.GetType())return false;var o = obj as PaiVisitEmpPK;if (o.Serialno != Serialno)return false;if (o.Rowno != Rowno)return false;return true;}
}

问题二:

解决了问题一,剩下就是实体类怎么使用这个主键类了

使用方法:

1)、实体类中不要映射主键字段属性;

2)、添加1中的主键类类型的ID属性,

3)、实体类继承主键类,

[Class(Lazy = true, Table = "PAI_VISIT_EMP")]
public class PaiVisitEmp : PaiVisitEmpPK
{public PaiVisitEmpPK ID { get; set; }//这里暂时这样写,后面需要修改[Property(TypeType = typeof(string), Column = "EMPID", Name = "Empid")]public virtual string Empid { get; set; }[Property(TypeType = typeof(string), Column = "ROLEVALUE", Name = "Rolevalue")]public virtual string Rolevalue { get; set; }[Property(TypeType = typeof(short), Column = "STOPFLAG", Name = "Stopflag")]public virtual short Stopflag { get; set; }[ManyToOne(Name = "GrantPaiVisit", Class = "Entities.PaiVisit", Column = "Serialno", Lazy = Laziness.False)]public virtual PaiVisit GrantPaiVisit { get; set; }...
}

这样我们其实就可以成功使用ISession().Get<T>(object)方法获取我们实体类的类对象,序列化后类似如下json格式:

 "xxx": {"id": {"serialno": "132122814165370555", "rowno": 4}, "empid": "1000240", "rolevalue": "03", "stopflag": 0, "grantPaiVisit": {"serialno": "132122814165370555", "orgidHosp": "01", "patipaytypeid": "0900", "innoHosp": 1, "reasonLeave": "00", "dateDayleft": "0001-01-01 00:00:00", "empidDayleft": "", "empnameDayleft": "", "dateDeath": "0001-01-01 00:00:00", "ehrUpflag": 0, "pa": {"patiid": "0002472212281414070555", "idcardtypeid": "10", "idcardtypename": "身份证", "idcard": "", "dateUpdate": "2022-12-28 14:44:14", "originid": "111498", "originname": "", "peraddressid": "111498", "peraddressname": "", "accountcode": "-", "ehrUpflag": 0, "userid": "", "platformid": "", "empi": "082633464"}}, "serialno": "", "rowno": 0}
}

这样可以看到我们需要的所有信息,但是仔细看看有问题,首先我们的实体表没有ID这个字段,所以有时候我们希望得到的数据及数据的结构跟数据库是一样的,二是序列化后json里面存在两个问题,一个是

"id": {"serialno": "132122814165370555", "rowno": 4
}, 

另一个是

"serialno": "",
"rowno": 0

这都不是我们想要的结果,这样就引出一个新问题;

问题三:

序列化后的数据与数据库中数据及数据的结构需要一致;

解决办法:

修改实体列如下

[Class(Lazy = true, Table = "PAI_VISIT_EMP")]public class PaiVisitEmp : PaiVisitEmpPK{private PaiVisitEmpPK _ID { get; set; }public virtual PaiVisitEmpPK ID{get => _ID;set{_ID = value;base.Serialno = value.Serialno;base.Rowno = value.Rowno;}}//public PaiVisitEmpPK ID { get; set; }//这行语法糖封装被换成上面的封装方式[Property(TypeType = typeof(string), Column = "EMPID", Name = "Empid")]public virtual string Empid { get; set; }[Property(TypeType = typeof(string), Column = "ROLEVALUE", Name = "Rolevalue")]public virtual string Rolevalue { get; set; }[Property(TypeType = typeof(short), Column = "STOPFLAG", Name = "Stopflag")]public virtual short Stopflag { get; set; }[ManyToOne(Name = "GrantPaiVisit", Class = "Entities.PaiVisit", Column = "Serialno", Lazy = Laziness.False)]public virtual PaiVisit GrantPaiVisit { get; set; }}

也就是我们不使用vs的封装语法糖,而是定义private属性_ID,封装public的属性访问器ID,这样就可以解决问题,此时序列化后json如下:

"xxx": {"empid": "1000240", "rolevalue": "03", "stopflag": 0, "grantPaiVisit": {"serialno": "132122814165370555", "orgidHosp": "01", "patipaytypeid": "0900", "innoHosp": 1, "reasonLeave": "00", "dateDayleft": "0001-01-01 00:00:00", "empidDayleft": "", "empnameDayleft": "", "dateDeath": "0001-01-01 00:00:00", "ehrUpflag": 0, "pa": {"patiid": "0002472212281414070555", "idcardtypeid": "10", "idcardtypename": "身份证", "idcard": "", "dateUpdate": "2022-12-28 14:44:14", "originid": "111498", "originname": "", "peraddressid": "111498", "peraddressname": "", "accountcode": "-", "ehrUpflag": 0, "userid": "", "platformid": "", "empi": "082633464"}}, "serialno": "132122814165370555", "rowno": 4}

这时候看起来就是我们想要的数据了;

以上内容属于个人整理,如有错误欢迎批评指正;

NHibernate Mapping Attribute实现复合主键映射相关推荐

  1. Hibernate的复合主键映射

    1>.学过hibernate的都知道用<id>来配置主键生成策略,显然,它只能配置主键是单列的表,对于联合主键的情况<id>就无能为力了.今天翻到个复合主键映射的资料,觉 ...

  2. Hibernate复合主键映射

    目录: 1. 实现方式一:将复合主键对应的属性与实体其他普通属性放在一起 2. 实现方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用 在日常开发中会遇到这样一种情况,数据库中的某张 ...

  3. hibernate中表的复合主键映射表

    成绩表Cj:学号和课程号是复合主键 映射文件Cj.hbm.xml: <?xml version="1.0"?> <!DOCTYPE hibernate-mappi ...

  4. mapper中mysql复合语句_MyBatis定义复合主键

    前为别名后为主查询getXXX语句中字段 SELECT colid,colname FROM table1 SELECT * FROM table2 WHERE id = #{id} AND name ...

  5. hibernate之初学复合主键

    Jar包什么的就看前面几篇文章,接下来介绍复合主键知识 首先是hibernate的配置文件hibernate,cfg.xml基本没有什么变化 <!DOCTYPE hibernate-config ...

  6. springboot jpa 复合主键 联合主键

    为什么80%的码农都做不了架构师?>>>    在开发中,数据库中定义了一个复合主键,这时候在映射不稍微处理下会有一点问题.什么does not define an IdClass错 ...

  7. 对逻辑主键、业务主键和复合主键的思考

    这几天对逻辑主键.业务主键和复合主键进行了一些思考,也在网上搜索了一下相关的讨论,相关讨论可以看最下面的参考链接.下面是自己基于 SQL Server 做的一些总结,其他数据库(Oracle.MySQ ...

  8. sql 复合主键 联合主键_学习SQL:主键

    sql 复合主键 联合主键 If you've already worked with databases, then you could hardly miss the term – Primary ...

  9. JPA复合主键的使用

    背景 人员信息和组信息的关联表中使用的USER_ID_和GROUP_ID_的联合主键,在维护组人员信息的时候,发现JPA打印的SQL只根据USER_ID_作为条件来更新数据,当B组存在zhangsan ...

最新文章

  1. oracle将213变成123,oracle 转换函数
  2. 微信企业号:shell定时发送图片 到 指定人
  3. wince 德赛西威2413_【图】GPS导航/Wince6.0系统 德赛西威迈腾车载导航改装评测_汽配中国网...
  4. 【Linux】一步一步学Linux——route命令(169)
  5. .Net常用正则判断方法
  6. 数据结构笔记--栈的总结及java数组实现简单栈结构
  7. 一款三搭_冬日穿搭指南!照着这八条万能公式穿,让你不冻还有型_
  8. 在线重定义的补充测试
  9. Java 核心五个类(File、Outputstream、Inputstream、Reader、Writer)一个接口(Serializable)...
  10. 2021-04-06梦笔记
  11. dubbo教程(绝对的入门到入土)
  12. 安装微软的消息队列服务器,MSMQ消息队列的安装、启用
  13. GDS和OTA未来之路
  14. 工作过程中积累的书签(链接)
  15. ARM基础(5) ARM通讯接口
  16. Java-绘图软件(Windows画板)
  17. 渲染器引入KaTeX 模块——实现实时渲染
  18. 痞子衡嵌入式:其实i.MXRT1050,1020,1015系列ROM也提供了FlexSPI driver API
  19. 互联网行业人事频繁变动:高速发展之忧
  20. jzxx1033能被5整除且至少有一位数字是5的所有整数的个数

热门文章

  1. 边缘计算招聘 :边缘不再「边缘」,计算无处不在
  2. R-可视化(五):饼图/圆环图
  3. 【c语言】求一个3行4列矩阵的外框的元素值之和
  4. 如何利用imagick合并2张图后为动态效果
  5. 在控制台程序中隐藏控制台窗口!
  6. 腾讯云服务器部署TomCat出现404
  7. VS2022(Visual Studio)发布ASP.NET Core Web API应用到Web服务器(IIS)
  8. carla学习笔记(五)
  9. 如何打开一个嵌在PC端应用的web窗口的控制台?
  10. 127.0.0.1是什么地址?localhost呢?