有 Java 编程相关的问题?

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

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

假设提供了以下映射:

<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(),我不会

非常感谢


共 (4) 个答案

  1. # 1 楼答案

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

    如果您使用的是spring,则可以使用OpenEntityManagerViewFilter,这样会话将保持打开状态,直到渲染视图为止

  2. # 2 楼答案

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

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

    如果需要支持不同的方言,您还可以确定其范围

    签出5.7. Auxiliary database objects

  3. # 3 楼答案

    您可以采取的另一种方法是使用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;
        }   
    }
    
  4. # 4 楼答案

    如前所述

    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.

    所以我的建议是:同时使用这两种方法

    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”

    问候,