如何在ejb 3.0中实现缓存?

时间:2013-12-26 09:29:04

标签: java-ee concurrency ejb ejb-3.0 java-ee-5

我有一个客户陷入了EJB 3.0环境。没有@Singleton,没有bean管理的并发: - (

ejb规范禁止考虑线程管理和同步,如何实现缓存?从本质上讲,我想要一些非同步的对象缓存来进行一些代价高昂的操作。

5 个答案:

答案 0 :(得分:1)

EJB 3.0规范第21.1.2章中说明了使用静态字段和同步的限制。它也解释了原因。

  

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

     

需要此规则来确保一致的运行时语义,因为   而某些EJB容器可能使用单个JVM来执行所有操作   企业bean的实例,其他人可以分发实例   跨多个JVM。

     

•企业bean不得使用线程   同步原语同步多个执行   实例

     

这与上述原因相同。同步不起作用   如果EJB容器跨越企业bean的实例   多个JVM。

如果通过单例POJO实现缓存,则可能存在以下风险:如果EJB容器跨多个JVM分布EJB实例(例如,在集群环境中),则每个JVM中实际存在多个缓存实例。

所以它取决于,

  • 如果应用程序未在群集环境中部署,则可以执行此操作。据我所知,WebLogic和GlassFish在一个JVM中运行一个服务器实例。
  • 如果不限制数据一致性,您也可以这样做。通常在谈论“缓存”时允许这样做。

如果它对您不起作用,可能您应该考虑在EJB容器之外缓存数据,例如放入Redis或Hazelcast。

答案 1 :(得分:0)

我怀疑我是否清楚地理解你的问题!以下示例基于weblogiceclipselink

如果您正在为您的EJB使用eclipselink JPA,您可以像这样单独为每个实体使用缓存:

@Entity
@Cache(type=CacheType.SOFT)

如果需要,还可以为persistence.xml文件中的所有实体启用缓存。这在属性字段(oracle doc's link)中就是这样的:

<persistence-unit name="XYZ">
...
    <class>com.stack.Test</class>
    <properties>
        ...
        <property name="toplink.cache.type.default" value="Soft"/>
        ...
    </properties>
</persistence-unit>

缓存类型可以是不同的,如Soft,Hard,Weak,Full等。每个缓存类型都有自己的含义。您可以从here找到有关此缓存类型的更多信息。

答案 2 :(得分:0)

EJB容器中是否禁止使用volatile变量? volatile int变量提供了一些对多线程代码有用的保证。如果线程看到volatile变量的变化,则可以安全地假设它看到之前发生的所有事情。

另一个想法是@Stateful bean只实例化一次(调用将由容器序列化)。不过,我不确定实施细节。

答案 3 :(得分:0)

嗯,我认为ConcurrentSkipListMap可能是解决方案:没有同步但仍然是线程安全的。

答案 4 :(得分:0)

我将Redis和Jedis一起用于内存中的临时值。

请参阅下面的链接

https://redislabs.com/lp/redis-java/

Redis带有用于多个操作系统的安装程序。

示例:

import redis.clients.jedis.Jedis; 

public class RedisStringJava { 
   public static void main(String[] args) { 
      //Connecting to Redis server on localhost 
      Jedis jedis = new Jedis("localhost"); 
      System.out.println("Connected"); 
      //set the data in redis string and expire in default time
      jedis.set("param_name", "Param value"); 
      // Get the stored data and print it 
      System.out.println("Stored string in redis:: "+ jedis.get("param_name")); 
   } 
}