【问题标题】:Is it possible to have foreign key enforced without object-to-object mapping?是否可以在没有对象到对象映射的情况下强制执行外键?
【发布时间】:2011-01-07 20:26:47
【问题描述】:

假设提供了以下映射:

<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
}

我了解,如果我将 &lt;many-to-one... 转换为 &lt;property...,这将起作用,但数据库不会强制执行外键。

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

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

非常感谢。

【问题讨论】:

  • 我强烈建议使用 LazyLoading 而不是重新发明轮子。您将获得类型安全的实体类、完全相同的性能,并且可能会取消自定义重新加载代码。请注意,如果使用不正确,即如果在会话关闭后请求延迟加载,则 LazyLoading 只会导致 LazyLoadingException。另请注意,请求对象的 id 不会导致对象被加载。我建议您发布一个关于您在使用 LazyLoading 时遇到的具体问题的问题。
  • 相信我,我确实使用 LazyLoading。这只是我做不到的数百个案例中的一个。否则我不会问。

标签: java hibernate foreign-keys hibernate-mapping


【解决方案1】:

如你所说

我知道如果我将 但数据库不会强制执行外键。

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

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"。

问候,

【讨论】:

  • 杰克逊如何适应这个
【解决方案2】:

您始终可以在 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

【讨论】:

    【解决方案3】:

    您可以采取的另一种方法是使用 B 映射而不是 A 映射来定义 FK。我已经添加了 JPA 代码,如果您不使用注释,则必须将其转换为您的休眠映射文件。

    @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;
        }   
    }
    

    【讨论】:

      【解决方案4】:

      我建议您将对象关联到对象以充分利用 Hibernate。我认为问题是你得到的例外。这是因为当您尝试获取惰性对象时,Hibernate 会话已经关闭。这个博客中有几篇文章给出了这个问题的答案,例如这个:link text

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

      【讨论】:

      • 感谢您的回答,但我完全清楚为什么会抛出延迟加载异常以及如何处理它们。但是,这是一个特殊情况,我希望框架更灵活并为我完成工作。因为这就是它们被写的原因,对吧?最后,我认为我对 O-R 映射框架的要求并不过分,不是吗?
      猜你喜欢
      • 1970-01-01
      • 2016-09-21
      • 2018-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 2013-10-22
      相关资源
      最近更新 更多