1

这是一个相当新手的问题 - 请知道我知道这一点。

我有一个无状态会话 bean,它需要一次加载一些数据并将其本地缓存在一个静态变量中,以供该 bean 的所有实例使用。可以通过实体 bean 访问数据。我想知道缓存实体实例是否安全,或者我是否应该克隆它。此外,该实体还具有子实体。

调用实体 Foo。一个 Foo 有一个 Bar。在我的会话 bean 中,我想做这样的事情:

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
}

我的问题:

  1. 这是一个坏主意吗?它甚至会起作用吗?

  2. 有没有更好的方法来加载 Foo 数据一次,可能不需要那个 getFoo() 方法?在加载 Session 类时静态执行它似乎是理想的。

新的(准确的)示例代码,每条评论:

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);
    }
}
4

1 回答 1

2

无状态会话 Bean (SLSB) 中不允许使用非最终静态字段。从 EJB3 规范,第 21.1.2 节:

企业 bean 不得使用读/写静态字段。允许使用只读静态字段。因此,建议将企业 bean 类中的所有静态字段声明为 final。

在跨多个 JVM 分布实例时,此规则用于确保一致性。

所以不是一个好主意。我的建议是依赖您的 JPA 提供者可能支持的二级缓存,并让他透明地处理它。

作为旁注,我真的很想知道为什么你的 bean 中有这条线:

EntityManager em = Container.getInstance().getEntityManager();

在托管环境中,您应该使用容器管理的实体管理器并将其注入您的 SLSB(使用@PersistenceContext注释)。

于 2010-07-09T17:45:42.433 回答