我最近开始玩Play! Java的框架,版本1.2.3(最新版本)。在测试框架时,我在尝试在名为Map
的Hibernate实体中持久保存FooSystem
对象时遇到了一个奇怪的问题。 Map对象将一个long映射到一个名为Foo
的Hibernate实体,声明为Map<Long, Foo> fooMap;
我的问题如下:创建了正确的表,因为我已经注释了它们。但是,当FooSystem
对象fs
保持不变时,fs.fooMap
中的数据不会!
以下是我为实体使用的代码。首先是Foo
:
package models.test;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import play.db.jpa.Model;
@Entity
public class Foo extends Model
{
@ManyToOne
private FooSystem foosystem;
public Foo(FooSystem foosystem)
{
this.foosystem = foosystem;
}
}
这是FooSystem
:
package models.test;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import play.db.jpa.Model;
@Entity
public class FooSystem extends Model
{
@ManyToMany(cascade = {CascadeType.ALL, CascadeType.PERSIST})
@JoinTable(
name = "fooMap",
joinColumns = @JoinColumn(name = "foosystem"),
inverseJoinColumns = @JoinColumn(name = "foo")
)
private Map<Long, Foo> fooMap = new HashMap<Long, Foo>();
public FooSystem()
{
Foo f1 = new Foo(this);
Foo f2 = new Foo(this);
fooMap.put(f1.getId(), f1);
fooMap.put(f2.getId(), f2);
}
public Map<Long, Foo> getFooMap()
{
return fooMap;
}
}
以下是我用来测试我的设置的Controller
课程:
package controllers;
import javax.persistence.EntityManager;
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();
em.persist(fs);
render();
}
}
游戏!框架自动为HTTP请求创建了一个事务。虽然数据已插入foo
和foosystem
表中,但是没有任何内容插入到foomap
表中,这是所需的结果。我该怎么办?我错过了什么?
答案 0 :(得分:4)
我设法使用Java Ka Baby的建议来解决这个问题。问题实际上不在我的Model
课程中;问题在于Controller
。具体来说,我是以错误的顺序保存实体。一旦我意识到使用@ElementCollection
上的Map<Long, Foo>
注释产生了与我手动指定的连接表相同的效果,我尝试过我想实验的地方,我重新考虑了如何保存我的实体。< / p>
在我上面发布的代码中,您可以在FooSystem
构造函数中看到两个Foo
个对象f1
和f2
被放入fooMap
在Foo
对象持久化之前。我意识到,如果f1
在放入地图时不在数据库中,JPA如何在连接表中将其ID用作外键?
如果你能看到我使用这种推理的方式,你可以看到,显而易见的答案是JPA 无法完成使用外键引用的惊人壮举一个不存在的密钥。奇怪的是Play!控制台没有记录我发布的原始代码的任何错误,即使它根本不正确。框架吞噬了在此过程中抛出的每个Exception
,或者我编写的代码应该生成Exception
。
因此,为了解决问题,我在对Foo
实体执行任何操作之前保留了它们。只有这样我才把它们放进fooMap
。最后,填充fooMap
后,我会保留FooSystem
实体。
以下是更正后的TestController
课程:
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();
}
}
而且,由于我更改了FooSystem
,以下是该类的最终代码:
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);
}
}