是否可以在没有对象到对象映射的情况下强制执行外键?

问题描述:

假设提供了以下映射:是否可以在没有对象到对象映射的情况下强制执行外键?

<class name="A" table="a_table"> 
    <id name="id"/> 
    <many-to-one name="entityB" column="fk_B" not-null="false" unique="true"/> 
</class> 

<class name="B" table="b_table"> 
    <id name="id"/> 
</class> 

Java类:

public class A { 
    private long id; 
    private B entityB; 
    // getters and setters skipped 
} 

是否有可能改变的Hibernate映射,使外键在启动仍在执行,创建由Hibernate,但是类A看起来将如下所示:

public class A { 
    private long id; 
    private long idOfB; 
    // getters and setters skipped 
} 

据我所知,如果我将<many-to-one...转换为<property...这可以工作,但外键不会被数据库强制执行。

我需要这样做,因为对象B可能(也可能不会)分别初始化这有时会导致 org.hibernate.LazyInitializationException: could not initialize proxy - no Session异常时a.getB()被称为发生。我宁愿将它作为long idOfB,并在需要时加载整个对象;这也会使加载对象A更快。

我相信我的问题是非常相似的this one,但所提供的解决方案(使用延迟加载)是不是在我的情况适合作为即使我打电话a.getB().getId(),我会得到LazyInitializationException,而如果我叫a.getIdOfB()我不会”吨。

非常感谢。

+0

我强烈建议使用LazyLoading而不是重新发明轮子。你会得到类型安全的实体类,性能完全一样,并且可能会取消自定义重载代码。 请注意,如果使用不正确,LazyLoading只会导致LazyLoadingException,即在会话关闭后请求延迟加载。另请注意,请求对象的ID不会导致加载对象。我建议你发布一个关于LazyLoading具体问题的问题。 – meriton 2010-01-25 18:50:18

+0

相信我,我确实使用LazyLoading。在我无法做到的情况下,这只是一个例子。否则我不会问。 – mindas 2010-01-26 10:26:49

+0

相关问题:[java的 - 休眠 - 外键而不是实体](http://stackoverflow.com/questions/6311776/hibernate-foreign-keys-instead-of-entities)。 – 2016-10-14 10:53:27

至于说

我明白,如果我转换<多到一个...成<属性...这将起作用,但外键不会被数据库强制执行

所以我的建议是:同时使用

public class EntityA { 

    private Integer idOfB; 

    private EntityB entityB; 

    // getter's and setter's 

} 

而且

<class name="A" table="a_table"> 
    <id name="id"/> 
    <property name="idOfB" column="fk_B" not-null="false" unique="true"/> 
    <many-to-one name="entityB" update="false" insert="false" column="fk_B"/> 
</class> 

注意当两个属性共享同一列,你必须把设置它在短短的一个物业。否则,Hibernate会抱怨一些错误。它解释了为什么我在entityB属性中定义update =“false”和insert =“false”。

问候,

+0

不错,漂亮!它的工作原理... – mindas 2010-01-26 17:16:42

+0

我将如何适应杰克逊 – gabber12 2015-07-05 20:30:31

你总是可以在Hibernate的hbm.xml文件手动创建外键的DDL:

<hibernate-mapping> 
    ... 
    <database-object> 
     <create>[CREATE FK]</create> 
     <drop>[DROP FK]</drop> 
    </database-object> 
</hibernate-mapping> 

你也可以此范围内,如果不同的方言需要得到支持。

退房5.7. Auxiliary database objects

另一个你可以采取的办法是与你的乙映射,而不是一个映射定义FK。我已经添加了JPA代码,如果您不使用注释,则必须将其转换为您的hibernate映射文件。

@Entity 
public class B 
{ 
    private long id; 
    private List<A> aList; 

    @Id 
    @Column(name = "ID") 
    public long getId() 
    { 
     return id; 
    } 

    @OneToMany 
    @JoinColumn(name = "B_ID") 
    public List<A> getAList() 
    { 
     return aList; 
    } 
    public void setId(long id) 
    { 
     this.id = id; 
    } 
    public void setAList(List<A> aList) 
    { 
     this.aList = aList; 
    }   
} 

A.java不会是这样的:

@Entity 
public class A 
{ 
    private long id; 
    private long idOfB; 

    @Id 
    @Column(name = "ID") 
    public long getId() 
    { 
     return id; 
    } 
    @Column(name = "B_ID") 
    public long getIdOfB() 
    { 
     return idOfB; 
    } 
    public void setId(long id) 
    { 
     this.id = id; 
    } 
    public void setIdOfB(long idOfB) 
    { 
     this.idOfB = idOfB; 
    } 
} 

我建议你对象对象相关联得到的Hibernate的全部优势。我认为问题是你得到的例外。这是因为当您尝试获取惰性对象时,Hibernate会话已经关闭。在这个博客中有几个帖子显示了这个问题的答案,例如这个:link text

如果您使用spring,可以使用OpenEntityManagerInViewFilter,这样会话将保持打开状态,直到视图呈现。

+0

感谢您的回答,但我完全意识到为什么延迟加载异常会抛出以及如何处理它们。然而,这是一个特殊情况,我希望框架更加灵活并为我完成工作。因为这就是他们写作的原因,对吧?最后,我不认为我所要求的对于O-R映射框架来说太多了,不是吗? – mindas 2010-01-26 10:37:45