Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 会话结束后是否可以安全地存储对实体Bean的引用?_Java_Jpa_Jakarta Ee_Ejb 3.0_Stateless Session Bean - Fatal编程技术网

Java 会话结束后是否可以安全地存储对实体Bean的引用?

Java 会话结束后是否可以安全地存储对实体Bean的引用?,java,jpa,jakarta-ee,ejb-3.0,stateless-session-bean,Java,Jpa,Jakarta Ee,Ejb 3.0,Stateless Session Bean,这是一个相当新的问题-请知道我知道这一点 我有一个无状态会话bean,它需要加载一些数据一次,并将其本地缓存在一个静态变量中,以供该bean的所有实例使用。可以通过实体bean访问数据。我想知道缓存实体实例是否安全,或者是否应该克隆它。此外,该实体还具有子实体 调用实体Foo。阿福有一个酒吧。在会话bean中,我想做如下操作: private static final FOO_ID = 123L; private static Foo foo; private static Foo getF

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

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

调用实体Foo。阿福有一个酒吧。在会话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
}
我的问题是:

  • 这是个坏主意吗?它会起作用吗

  • 有没有更好的方法可以一次性加载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类中的所有静态字段声明为final

    此规则用于确保跨多个JVM分发实例时的一致性

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

    作为旁注,我想知道为什么你的bean中有这样一行:

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

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

    回想起来,我的示例代码并不能准确反映我要做的事情。将在原始帖子中添加新示例。基本上,我的问题是如何完成FooHelper构造函数的注释部分。@user190758我的答案仍然适用:使用JPA提供程序的二级缓存功能,为您透明地缓存
    Foo
    实体。这就是方法。所以只要继续,每次都取它,然后依靠底层在内存中保留一个副本,除非真的需要,否则不要访问数据库。对我有用。@user190758:没错,就是这样。