I managed to solve this problem using the advice of Java Ka Baby. The issue was actually not in my Model
classes; the problem lay within the Controller
. Specifically, I was saving the entities in the wrong order. Once I realized that using the @ElementCollection
annotation on the Map<Long, Foo>
produced the same effects as the join table I was manually specifying, I tried I thought experiment where I re-thought how I was saving my entities.
In the code I posted above, you can see in the FooSystem
constructor that two Foo
objects, f1
and f2
, are put into fooMap
before the Foo
objects are persisted. I realized that if f1
is not in the database when it is put into the map, how is JPA able to use its ID as a foreign key in the join table?
If you can see where I'm going with this line of reasoning, you can see that the obvious answer is that JPA is not able to accomplish this amazing feat of using a foreign key to reference a nonexistent key. The bizarre thing is that the Play! console did not note any errors at all for the original code I posted, even though it was not correct at all. Either the framework swallowed every Exception
thrown during the process, or I've written code that should produce an Exception
.
So to fix the problem, I persisted the Foo
entities before any operations were performed on them. Only then did I put them into fooMap
. Finally, once fooMap
was populated, I persisted the FooSystem
entity.
Here is the corrected TestController
class:
package controllers;
import javax.persistence.EntityManager;
import models.test.Foo;
import models.test.FooSystem;
import play.db.jpa.JPA;
import play.mvc.Controller;
public class TestController extends Controller
{
public static void index() {
EntityManager em = JPA.em();
FooSystem fs = new FooSystem();
Foo f1 = new Foo(fs);
Foo f2 = new Foo(fs);
f1.save();
f2.save();
fs.put(f1.getId(), f1);
fs.put(f2.getId(), f2);
fs.save();
render();
}
}
And, since I changed FooSystem
, here is the final code for that class:
package models.test;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import play.db.jpa.Model;
@Entity
public class FooSystem extends Model
{
@ElementCollection
private Map<Long, Foo> fooMap = new HashMap<Long, Foo>();
public FooSystem()
{
}
public Map<Long, Foo> getFooMap()
{
return fooMap;
}
public void put(Long l, Foo f)
{
fooMap.put(l, f);
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…