I can't post the code and mapping files, for the typical reasons. However, they're not really necessary as I'm not looking for someone to diagnose a defect. There's nothing going wrong, Hibernate is operating correctly.
What I'm looking for is a technique, perhaps some element of the Hibernate API I've overlooked, some clever use of interceptors or event listeners, etc., that will allow me to insert a new record into a table that has many-to-one references to other tables, but without having to first SELECT the referents.
If it helps, here's a simplified scenario. Assume the following classes:
Code:
public class A
{
private Integer key;
private B b;
public Integer getKey() { return key; }
public void setKey(Integer key) { this.key=key; }
public B getB() { return b; }
public void setB(B b) { this.b = b; }
};
Code:
public class B
{
private Integer key;
private String value;
public Integer getKey() { return key; }
public void setKey(Integer key) { this.key=key; }
public String getValue() { return value; }
public void setValue() { this.value = value; }
}
And the following mappings
Code:
<hibernate-mapping>
<class name="A">
<id name="key"/>
<many-to-one name="b"/>
</class>
<class name="B">
<id name="key"/>
<property name="value"/>
</class>
</hibernate-mapping>
And, finally, the method I'm trying to implement:
Code:
public createA(Integer bKey)
{
A a = new A();
a.setB(session.load(B.class, bKey)); // Here's the question
session.save(a);
}
Now, what I would like to have Hibernate do is issue the following:
Code:
INSERT INTO A (B) VALUES (?)
Where "bKey" is substituted for the parameter. What Hibernate does, of course is issue:
Code:
SELECT KEY,VALUE FROM B WHERE KEY=?
INSERT INTO A (B) VALUES (?)
where "bKey" is substituted for both parameters. That makes sense -- after all I did tell Hibernate to "load" the B instance -- but I want to avoid that extra SELECT statement. So, how can I associate the B instance with the new A instance without actually loading the B?
Of course, in this trivial example, the best approach would be to bypass Hibernate and simply use JDBC, or else create an alternative mapping of A that models the B relationship as a property, rather than a relationship. Something like:
Code:
public class DirectA
{
private Integer key;
private Integer bKey;
public Integer getKey() { return key; }
public void setKey(Integer key) { this.key=key; }
public Integer getBKey() { return bKey; }
public void setBKey(Integer bKey) { this.bKey = bKey; }
};
Code:
<hibernate-mapping>
<class name="DirectA" table="A">
<id name="key"/>
<property name="bKey" column="B"/>
</class>
</hibernate-mapping>
Then I could write:
Code:
public createA(Integer bKey)
{
DirectA directA = new DirectA();
directA.setBKey(bKey);
session.save(directA);
}
But the real-world case is not nearly so trivial. In fact, my 'A' class is rather large and complex and has many many-to-one mappings to other classes. That being the case, maintaining a separate mapping is an undesirable maintenance burden. Perhaps one I'll have to accept if I can't find another way, but undesirable.
My question then, is: Is there a way to avoid the extra SELECT without creating the additional mapping, and without bypassing Hibernate?
Thanks,
Shawn.