为什么我的@ApplicationScope CDI bean没有更新?

时间:2011-12-04 16:20:41

标签: java jpa jsf-2 cdi

在我的应用程序中,我有一个@ApplicationScoped CDI bean来存储数据库中的一些信息:

@Named
@ApplicationScoped
public class MrBean {
   @EJB
   private SoyaBean soyaBean;
   private List<Toys> myToys;

   @PostConstruct
   public void prepareMrBean() {
      this.myToys = soyaBean.getToys();
   }

   public void updateToys() {
      this.myToys = soyaBean.getToys();
   }
}

我还有一个AddToy.xhtml页面,它只是将一个玩具添加到数据库中。支持bean如下:

@Named
@RequestScoped
public class MrsBean {
   @EJB
   private SoyaBean soyaBean;
   @Inject
   private MrBean mrBean;

   public void addToy() {
      this.soyaBean.addToy();
      this.mrBean.updateToys();
   }
}

由于数据库中添加了新玩具,我想更新mrBean中的玩具列表。但是,即使mrsBean调用mrBean.updateToys(),mrBean中的玩具列表也根本没有更新。我有另一个带有@RequestScoped支持bean的ViewToys.xhtml来查看玩具列表,我没有看到列表得到更新。

如果有人能就如何解决这个问题给我建议,我将非常感激。

UPDATE :这是我的SoyaBean实现:

@Stateless
public class SoyaBeanImpl implements SoyaBean {
   @PersistenceContext()
   private EntityManager em;

   @Override
   public List<Toys> getToys() {
      Query q = em.createQuery("SELECT T from Toys T");
      return (List<Toys>) q.getResultList();
   }

   @Override
   public void addToy() {
      Toys newToy = new Toys();
      em.persist(newToy);
   }
}

更新2 如果有人能告诉我除了令人不安的方式以外,我能以任何方式实现同​​样的目标,我也非常感激。

致以最诚挚的问候,

James Tran

2 个答案:

答案 0 :(得分:0)

假设您的代码中没有重大技术错误,这些错误通常与您所暗示的实体经理返回的数据状态有关。

Cluprit:数据库?

当然,您可能在底层数据库中遇到缓存问题。但是,鉴于您对system.out语句的描述,这不太可能。

罪魁祸首:豆子?

更可能的罪魁祸首是查询结果以某种方式缓存在bean中,或者更确切地说,在查询结果集返回值中。如果您的测试数据库允许脏读,那可能是一个解释。例如,可以通过使用@Interceptor在任何对getToys()的调用之前刷新查询来检查这一点。

另一个潜在的陷阱:误认为无状态与缓存。

最后:关于无国籍的简短说明。虽然你是正确的,一般来说,bean的无状态应该导致数据不是陈旧的 - 但情况并非总是如此。 EJB上下文中无状态bean的真正定义是那些bean在应用程序生命周期的过程中不具备状态。

总之,有三种不同的方法可以解决您的问题:

1)确保数据库在脏读时没有做任何有趣的事情。 2)测试是否拦截对getToys()的调用,并且运行/验证数据库查询没有问题 3)确保您所需的无状态类型实际上是由您的ejb容器实现的。

答案 1 :(得分:0)

问题是所有SQL查询的结果都被缓存了。因此,即使我试图刷新玩具列表,它只收到旧的结果。我通过将文件Shared Cache Mode中的选项persistence.xml设置为None来解决了这个问题。

我认为根本不使用缓存不是一个好选择。因此,如果有人能告诉我如何在不关闭缓存的情况下实现相同的结果,我将非常感激。