NHibernate Mapping Attribute实现复合主键映射
当我在学习使用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实现复合主键映射相关推荐
- Hibernate的复合主键映射
1>.学过hibernate的都知道用<id>来配置主键生成策略,显然,它只能配置主键是单列的表,对于联合主键的情况<id>就无能为力了.今天翻到个复合主键映射的资料,觉 ...
- Hibernate复合主键映射
目录: 1. 实现方式一:将复合主键对应的属性与实体其他普通属性放在一起 2. 实现方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用 在日常开发中会遇到这样一种情况,数据库中的某张 ...
- hibernate中表的复合主键映射表
成绩表Cj:学号和课程号是复合主键 映射文件Cj.hbm.xml: <?xml version="1.0"?> <!DOCTYPE hibernate-mappi ...
- mapper中mysql复合语句_MyBatis定义复合主键
前为别名后为主查询getXXX语句中字段 SELECT colid,colname FROM table1 SELECT * FROM table2 WHERE id = #{id} AND name ...
- hibernate之初学复合主键
Jar包什么的就看前面几篇文章,接下来介绍复合主键知识 首先是hibernate的配置文件hibernate,cfg.xml基本没有什么变化 <!DOCTYPE hibernate-config ...
- springboot jpa 复合主键 联合主键
为什么80%的码农都做不了架构师?>>> 在开发中,数据库中定义了一个复合主键,这时候在映射不稍微处理下会有一点问题.什么does not define an IdClass错 ...
- 对逻辑主键、业务主键和复合主键的思考
这几天对逻辑主键.业务主键和复合主键进行了一些思考,也在网上搜索了一下相关的讨论,相关讨论可以看最下面的参考链接.下面是自己基于 SQL Server 做的一些总结,其他数据库(Oracle.MySQ ...
- sql 复合主键 联合主键_学习SQL:主键
sql 复合主键 联合主键 If you've already worked with databases, then you could hardly miss the term – Primary ...
- JPA复合主键的使用
背景 人员信息和组信息的关联表中使用的USER_ID_和GROUP_ID_的联合主键,在维护组人员信息的时候,发现JPA打印的SQL只根据USER_ID_作为条件来更新数据,当B组存在zhangsan ...
最新文章
- oracle将213变成123,oracle 转换函数
- 微信企业号:shell定时发送图片 到 指定人
- wince 德赛西威2413_【图】GPS导航/Wince6.0系统 德赛西威迈腾车载导航改装评测_汽配中国网...
- 【Linux】一步一步学Linux——route命令(169)
- .Net常用正则判断方法
- 数据结构笔记--栈的总结及java数组实现简单栈结构
- 一款三搭_冬日穿搭指南!照着这八条万能公式穿,让你不冻还有型_
- 在线重定义的补充测试
- Java 核心五个类(File、Outputstream、Inputstream、Reader、Writer)一个接口(Serializable)...
- 2021-04-06梦笔记
- dubbo教程(绝对的入门到入土)
- 安装微软的消息队列服务器,MSMQ消息队列的安装、启用
- GDS和OTA未来之路
- 工作过程中积累的书签(链接)
- ARM基础(5) ARM通讯接口
- Java-绘图软件(Windows画板)
- 渲染器引入KaTeX 模块——实现实时渲染
- 痞子衡嵌入式:其实i.MXRT1050,1020,1015系列ROM也提供了FlexSPI driver API
- 互联网行业人事频繁变动:高速发展之忧
- jzxx1033能被5整除且至少有一位数字是5的所有整数的个数