【问题标题】:Hibernate Many-to-Many mapping not working correctly on insert休眠多对多映射在插入时无法正常工作
【发布时间】:2011-09-03 18:22:00
【问题描述】:

我继承了一个 Spring+NHibernate c# 应用程序,我们正在对它进行大修(而且我对 NHibernate 还很陌生)。数据库中设置的用户/角色不是最佳的,所以我正在重写它,因为项目的一部分无论如何都在添加新功能。但是,翻译成 NHibernate 的工作不正常。这是我设置的相关部分:

数据库: 3张桌子; USERS、ROLES 和 USERS_XREF_ROLES(即连接/桥接表)

用户.hbm.xml:

<set name="Roles" table="[USERS_XREF_ROLES]" lazy="false" order-by="[FK_ROLES] asc" cascade="all">
    <key column="[FK_USERS]" />
    <many-to-many class="UserRole" column="[FK_ROLES]" />
</set>

用户角色.hbm.xml:

<set name="Users" inverse="true" table="[USERS_XREF_ROLES]" lazy="false" >
    <key column="[FK_ROLES]" />
    <many-to-many class="User" column="[FK_USERS]" />
</set>

另请注意,UserRole 类中最初没有设置“用户”;我添加了它是因为添加了桥接/连接表和 SO 上的另一篇文章,其中提到使用桥接/连接表的反向集。所有 SELECT 都工作正常。我检查了多个用户并测试了他们应该拥有的权限。但是,当我尝试创建一个新用户时,它显然也在尝试插入 ROLES:

错误:休眠操作:无法插入:[UserRole][SQL: INSERT INTO [ROLES] ([VALUE]) VALUES (?);选择 SCOPE_IDENTITY()]; SQL [INSERT INTO [ROLES] ([VALUE]) VALUES (?) 的未分类 DataException;选择 SCOPE_IDENTITY()];错误代码 [];无法将值 NULL 插入到列 'NAME'、表 'ROLES' 中;列不允许空值。插入失败。该语句已终止。

一个新用户显然应该在 USERS 和 USERS_XREF_ROLES 中生成一个 INSERT,而不是 ROLES。那么,我在这里做错了什么?谢谢。

更新:我试图让我的问题更清楚。我的大问题是,我发现的所有示例都显示将两个相关对象插入每个相应的表和连接表中。我希望能够添加具有现有角色的用户。创建用户时,我不希望在 ROLES 表中发生插入。创建用户时应始终将一条记录插入 USERS,将一条或多条记录插入 USERS_XREF_ROLES,但永远不要插入 ROLES,因为用户将始终被分配到现有角色。我希望这更清楚。我还没有找到一个例子来说明这一点,这一定是一件很常见的事情。

【问题讨论】:

    标签: c# .net sql nhibernate


    【解决方案1】:

    一个新用户显然应该在 USERS 和 USERS_XREF_ROLES 中生成一个 INSERT,但不是 ROLES。那么,我在这里做错了什么?谢谢。

    这句话让我很困惑,我可能只是误解了,但如果 USERS_XREF_ROLES 是一个桥接表,那么为什么 INSERT 到 USERS 需要插入到桥接表中?可能存在未分配角色的用户,不是吗?考虑到这一点,我希望问题不在于 nHibernate 映射,而在于实例化 c# 对象的方式。也许正在使用 User 类的实例化创建一个未绑定的 Role 类?

    【讨论】:

    • 你是对的——一个记录可以存在于 USERS 表中,而在 USERS_XREF_ROLES 表中没有相应的记录。但是,业务要求是所有用户必须至少分配一个角色。我的假设是 NHibernate 处理所有的插入逻辑,并且它都可以通过 XML 进行配置。我没有用于桥接表的类(这是正确的处理方式?)那么我如何确保将记录插入到 USERS 和 USERS_XREF_ROLES 中?我认为这真的是我不明白的地方。
    • 我不知道 nHibernate 可以强制执行这样的要求,因为它必须知道一些默认角色才能分配用户。我的建议是,任何此类要求都由您的 c# 代码中的数据模型强制执行。数据库触发器也可以工作,但我个人对此有偏好。
    • 是的,我也没有数据库触发器。所以,你的意思是,如果我用我设置的方式声明 cascade="all" ,它会尝试在所有 3 个表中插入一条记录?看起来这将是一个非常普遍的情况,这让我认为应该有一个非常普遍、直接的解决方案。然而,我真的没有通过谷歌找到太多东西。因为无论如何我都在重写它,所以我对不同的解决方案持开放态度。
    • 我想我可能还没有完全理解你。如果您总是希望将新用户分配给某个角色,您的选择是肯定的,要么必须为所有三个表生成插入,要么必须将现有的 nHibernate 绑定角色对象添加到用户类的角色集合。 (如果您向我展示您的用户和角色类的基本结构以及您用于创建新用户的代码,我的部分困惑可能会得到解决。)
    • 对不起,我被拉到另一个项目。我已经更新了我原来的问题,希望我的问题现在更清楚了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-02
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多