我最近开始玩Play!Java框架1.2.3版(最新)。在测试框架时,尝试Map在名为的Hibernate实体中保留对象时遇到了一个奇怪的问题FooSystem。地图对象映射长到Hibernate的实体,我呼吁Foo,随着申报Map<Long, Foo> fooMap;
Map
FooSystem
Foo
Map<Long, Foo> fooMap;
我的问题如下:按照我的注释创建正确的表。但是,当FooSystem对象fs持久化时,其中的数据fs.fooMap就不会!
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我用来测试设置的课程:
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表中,这是理想的结果。我该怎么办?我想念什么?
foo
foosystem
foomap
我设法使用Java Ka Baby的建议解决了这个问题。这个问题实际上不在我的Model课堂上;问题在于Controller。具体来说,我以错误的顺序保存了实体。一旦意识到使用@ElementCollection注释Map<Long, Foo>产生的效果与我手动指定的连接表相同,便尝试进行实验,重新思考如何保存实体。
Model
@ElementCollection
Map<Long, Foo>
在上面发布的代码中,您可以在FooSystem构造函数中看到在持久化对象之前已放入两个Foo对象f1和。我意识到,如果将它放入地图中时不在数据库中,那么JPA如何将其ID用作联接表中的外键?f2``fooMap``Foo``f1
f1
f2``fooMap``Foo``f1
如果您可以看到我要使用的这种推理方法,那么您会发现显而易见的答案是,JPA 无法 完成使用外键引用不存在的键这一惊人的壮举。奇怪的是那出戏!控制台根本没有记录我发布的原始代码的任何错误,即使它根本不正确。要么框架吞噬了Exception在此过程中抛出的所有错误,要么是我编写了 应该 产生的代码Exception。
Exception
因此,为解决此问题,我在对Foo实体执行任何操作之前将其保留下来。然后才把它们放进去fooMap。最后,一旦fooMap填充完毕,我便保留了该FooSystem实体。
fooMap
这是更正后的TestController类:
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); } }