【问题标题】:Hibernate - Foreign keys instead of EntitiesHibernate - 外键而不是实体
【发布时间】:2011-09-12 19:07:45
【问题描述】:

目前,Hibernate 允许我直接使用

加载由 * 对一关系定义的对象
entity1.getEntity2()

是否可以获取外键而不是对象?

我看到的当前方法是添加到我的映射中:

@JoinColumn(name="message_key")
@ManyToOne(targetEntity=Message.class,fetch=FetchType.LAZY)
private Message message;  //these lines currently exist

@Column(name="message_key")
private Long message_fk; //the idea is to add those 2 lines

有没有更好的方法来获取外键,还是只有这个?

【问题讨论】:

    标签: java hibernate mapping foreign-keys


    【解决方案1】:
    Long fk = entity1.getEntity2().getId();
    

    这应该可行。只有当您将复合主键作为外键引用时,它才会起作用,但您的解决方案在这种情况下也不起作用。考虑到我的解决方案,即使是复合键也不会那么难看。

    Long fkField1 = entity1.getEntity2().getCol1();
    String fkField2 = entity1.getEntity2().getCol2();
    

    类似的东西会起作用。

    编辑: 再考虑一下您提出的解决方案,它无论如何都行不通,因为 Hibernate 已经尝试为映射关系自动创建 FK 字段,因此定义另一个 @Column 只会尝试绑定到具有相同名称的第二列。

    【讨论】:

    • 我不喜欢这个解决方案,因为它需要加载外键引用的实体。有没有办法避免它?另外:@Column 将被视为单独的参数,而不是 FK。至少我是这么认为的。
    • 关于@Column 评论:请参阅 Affe 的回答了解我的意思,他的解释更清楚。关于实体被加载,你是对的,它会导致你的延迟获取类加载。您的问题并未说明它试图避免获取,只是“我如何获得 FK 值?”;你可能想编辑它。
    • 其实如果只是获取关联实体的id值,Hibernate不需要加载整个实体。在延迟加载中,它已经从实体映射表中的 FK 加载了 ID。
    • 如果 entity1.entity2 = null,此代码将抛出 NPE
    【解决方案2】:

    是的,你可以这样做。您只需要为 hibernate 明确哪个是它应该维护的映射,如下所示:

    @Column(name="message_key", updatable=false, insertable=false)
    private Long message_fk;
    

    【讨论】:

    • 如何指定此 ID 指的是哪个实体?数据库模式应该包含真正的外键约束,这是无法从您的注释中识别出来的......
    • 建议是在实体关系正常全映射的基础上再做这个映射,如原题所示。
    • 当hibernate似乎混淆了哪个是对象,哪个是键时,我得到了一个classcastexception
    • 有什么方法可以“完全替代”消息实体本身?
    • 那看起来不太漂亮。考虑到大多数代码库对成员使用驼峰式大小写
    【解决方案3】:

    如果您仍然想要引用您的实体,但不想从数据库中加载它只是为了获取外键,那么您的方法是正确的。将 insertable 和 updatabale = false 添加到 Column 属性,以防止丢失对实体的正确引用。

    @JoinColumn(name = "message_key")
    @ManyToOne(targetEntity = Messages.class, fetch = FetchType.LAZY)
    private Messages message;
    
    @Column(name = "message_key", insertable = false, updatable = false)
    private Long message_fk;
    

    【讨论】:

    • 有人试过反之亦然,所以我只需要插入一个id,hibernate就可以正确获取实体?
    • @kaiser 你能根据 ID 获取整个实体吗?
    【解决方案4】:

    实际上,如果 FetchType 为 LAZY,则仅加载外键而不是消息对象是默认的 Hibernate 行为。这就是为什么在指定 LAZY FetchType 时要加载对象的代理。

    外键是不直接可见的,但它当然是OneToMany关系“一”端的对象的键。

    但是,对于基于字段的访问类型(例如,在您的情况下,注释放置在字段上),存在一个未解决的休眠问题:休眠从数据库加载代理后面的整个对象。 (http://blog.xebia.com/2009/06/13/jpa-implementation-patterns-field-access-vs-property-access/)

    我的具体建议是(例如,“正确”的答案在我的情况下不起作用):

    • 直接使用消息对象,因为 Hibernate 仅在需要非外键数据时才加载它。不要为外键指定额外的字段。
    • 切换类以使用属性访问,即定义 getter 和 setter,并将您的注释从字段放到 getter。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多