EJB@Asynchronous在JSF中检索实时插入的行似乎是线程锁定的



我正在努力实现以下目标:

EJB3 Singleton

@Singleton
@Startup
public class SomeSingleton implements SomeSingletonLocal  {
    // Entity Manager injection
    private EntityManager _entity_manager;
    @Override
    @Asynchronous
    public void createScenario(){
        method1();
        method2();
        // ...
    }
    public void method1(){
        // Persist an Event in a Database.
    }
    public void method2(){
        // Persist an Event in a Database.
    }
}

托管Bean

@ManagedBean
@RequestScoped
public class SomeManagedBean{
    // Entity Manager injection
    private EntityManager _entity_manager;
    @EJB
    private SomeSingletonRemote _singleton;
    public void createScenario(){
        _singleton.createScenario();
    }
    public List<Event> getEventList(){
        // Retrieve events from database
    } 
}

JSF视图

<h:form>
    <p:commandButton value="Start Long Stuff" 
        actionListener="#{SomeManagedBean.createScenario}" />
    <h:outputText id="count" value="#{SomeManagedBean.getEventList.size()}" />
            <p:poll interval="1" update="count" />
</h:form>

日志

->SomeManagedBean.getEventList()
&lt-SomeManagedBean.getEventList()//大小=0

//Buton点击
->SomeManagedBean.createScenario()
 nbsp nbsp nbsp;->SomeSingleton.createScenario()
&lt-SomeManagedBean.createScenario()

->SomeManagedBean.getEventList()//将在SomeSingleton.createScenario结束时结束
->SomeSingleton.method1()
&lt-SomeSingleton.method1()//persistent

->SomeSingleton.methodN()
&lt-SomeSingleton.methodN()//持久

&lt-SomeSingleton.createScenario()

&lt-SomeManagedBean.getEventList()//size=N

我希望在两个methodI()调用之间(即每秒)至少有一个getEventList调用。当它进入SomeSingleton.createScenario()时,我不知道getEventList为什么会暂停。

看起来createScenario中的实体管理器或事务有一个锁。这是再入问题吗?

@Singleton在默认情况下确实是读/写锁定的。这与事务无关,而是与并发性有关。另请参阅有关该主题的a.o.Java EE 7教程。

解决该问题的一种方法是将@ConcurrencyManagement设置为BEAN。通过这种方式,您基本上告诉容器根本不用担心并发性,并且您自己承担所有责任。

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class SomeSingleton {}

另一种方法是在类或只读方法上显式地将@Lock设置为READ,以便可以同时调用它们。只有当在同一实例上调用具有显式@Lock(LockType.WRITE)的方法时,才会发生锁。

@Singleton
@Lock(LockType.READ)
public class SomeSingleton {}

最新更新