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 separate开发者_Python百科ly 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.
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,
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
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;
}
}
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.
精彩评论