在会话结束后,安全存储对实体bean的引用?
-
13-09-2020 - |
题
这是一个漂亮的新手问题 - 请知道我意识到这一点。
我有一个无状态的会话bean,需要加载一些数据并在静态变量中本地缓存,以便由该bean的所有实例使用。可以通过实体bean访问数据。我想知道它是否安全缓存实体实例,或者我应该克隆它。此外,此实体还具有子实体。
调用实体foo。Foo有一个酒吧。在我的会话豆中,我想做这样的事情:
private static final FOO_ID = 123L;
private static Foo foo;
private static Foo getFoo(EntityManager em) {
if (foo != null)
return foo;
return foo = (Foo) em.find(Foo.class, FOO_ID);
}
public void someBusinessMethod() {
EntityManager em = Container.getInstance().getEntityManager();
Foo foo = getFoo(em);
Bar bar = foo.getBar();
// do some stuff with foo and bar
}
.
我的问题:
-
这是一个坏主意吗?它甚至可以工作吗?
-
是否有更好的方法来加载foo数据一次,可能无需该getfoo()方法?当加载会话类时,静态地执行似乎是理想的。
新(准确)示例代码,按评论:
public class Foo { // entity
private Long id;
private String name;
// getters and setters
}
public class Bar { // entity
private Long id;
private String name;
// getters and setters
}
public class FooHelper implements Helper {
private static final long FOO_ID = 123L;
private Foo foo;
public FooHelper() {
// use FOO_ID to look up a Foo & cache it locally
}
@Override
public void addBar(EntityManager em) {
Bar bar = new Bar();
bar.setName(foo.getName());
em.persist(bar);
}
public class StatelesSessionBean {
private static final Helper helper = new FooHelper();
public void someBusinessMethod() {
@PersistenceContext
EntityManager em;
helper.addBar(em);
}
}
.解决方案
无状态会话bean(slsb)中不允许使用非最终静态字段。从EJB3规范,第21.1.2节:
企业bean不得使用读/写静态字段。允许使用只读静态字段。因此,建议企业bean类中的所有静态字段被声明为最终。
此规则在有跨多个JVMS分发实例时确保一致性。
所以不是一个好主意。我的建议是依赖于第二级缓存,即你的JPA提供商可能支持,让他透明地处理。
作为侧面笔记,我真的想知道你为什么在你的bean中有这个行:
EntityManager em = Container.getInstance().getEntityManager();
.
在托管环境中,您应该使用 container managed 实体管理器,并将其注入SLSB(使用@PersistenceContext
注释)。
不隶属于 StackOverflow