有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java休眠外键而不是实体

目前,Hibernate允许我使用直接加载由*-to-one关系定义的对象

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

是否有更好的方法获取外键,或者这是唯一的方法


共 (4) 个答案

  1. # 1 楼答案

    如果您仍然希望引用实体,但不想从数据库中加载它来获取外键,那么您的方法是正确的。将insertable和Updateable=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;
    
  2. # 2 楼答案

    是的,你能做到。您只需要为hibernate明确它应该维护的映射,如下所示:

    @Column(name="message_key", updatable=false, insertable=false)
    private Long message_fk;
    
  3. # 3 楼答案

    实际上,如果FetchType是惰性的,默认的Hibernate行为是只加载外键而不是消息对象。这就是为什么当您指定LAZY FetchType时,要加载的对象会有代理

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

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

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

    • 直接使用message对象,因为Hibernate仅在需要非外键数据时才会加载它。不要为外键指定其他字段
    • 切换类以使用属性访问,即定义getter和setter,并将注释从字段放到getter
  4. # 4 楼答案

    Long fk = entity1.getEntity2().getId();
    

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

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

    像这样的办法会管用的

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