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

发布于 2024-08-19 05:40:45 字数 1330 浏览 2 评论 0 原文

假设提供了以下映射:

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

我知道如果我将 转换为 这会起作用,但是外国数据库不会强制执行密钥。

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

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

预先非常感谢。

Assuming the following mappings are provided:

<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 class:

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

Is it possible to change the Hibernate mapping so that foreign key is still enforced and created by Hibernate upon startup, but class A would look like as the following:

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

I understand that if I convert <many-to-one... into a <property... this would work, but foreign key would not be enforced by the database.

I need to do this because object B might (or might not) be initialized separately which sometimes causes
org.hibernate.LazyInitializationException: could not initialize proxy - no Session exceptions to occur when a.getB() is called. I would prefer to have it as a long idOfB and load whole object whenever is necessary; this would also make loading of object A quicker.

I believe my question is very similar to this one, yet the offered solution (to use lazy loading) is not appropriate in my case as even if I call a.getB().getId(), I'd get LazyInitializationException whereas if I call a.getIdOfB() I wouldn't.

Thanks very much in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

南风几经秋 2024-08-26 05:40:45

正如所说

我知道,如果我将<多对一...转换为<属性...,这会起作用,但数据库不会强制执行外键。< /p>

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

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

问候,

As said

I understand that if I convert <many-to-one... into a <property... this would work, but foreign key would not be enforced by the database.

So my advice is: use both

public class EntityA {

    private Integer idOfB;

    private EntityB entityB;

    // getter's and setter's

}

And

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

Notice when two properties share the same column, you have to put settings about it in just one property. Otherwise, Hibernate will complain some errors. It explains why i define update="false" and insert="false" in entityB property.

regards,

我很OK 2024-08-26 05:40:45

您始终可以在 hibernate hbm.xml 文件中手动创建外键 DDL:

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

如果需要支持不同的方言,您也可以确定此范围。

查看 5.7。辅助数据库对象

You could always create the Foreign Key DDL manually in your hibernate hbm.xml file:

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

You can also scope this if different dialects need to be supported.

Check out 5.7. Auxiliary database objects

太阳公公是暖光 2024-08-26 05:40:45

您可以采取的另一种方法是使用 B 映射而不是 A 映射来定义 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;
    }   
}

Another approach you could take is to define the FK with your B mapping rather than the A mapping. I've added the JPA code, you'd have to translate this to your hibernate mapping file if you're not using annotations.

@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 would not look like this:

@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;
    }   
}
尴尬癌患者 2024-08-26 05:40:45

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

如果您使用 spring,您可以使用 OpenEntityManagerInViewFilter,以便会话将保持打开状态,直到视图渲染。

I recommend you to associate objects to objects to get full advantages of Hibernate. I think the problem is the exception you get. This is because Hibernate session is already closed when you try to get the lazy object. There are several posts in this blog which show answers to this problem, for example this one:link text.

In case you're using spring you can use OpenEntityManagerInViewFilter so the session will keep opened until the view is renderes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文