所以我从BalusC的这篇文章中读到了如何阻止无状态会话bean在被JSF访问时不断地颠簸数据存储(例如DB)(这可能会/将进行多次调用)所以我已经实现了我的代码我想这是符合BalusC所发布的精神(以及我见过的关于这个问题的"最佳实践"的其他论坛帖子).
我的无状态会话bean看起来像这样:
@Stateless
@Named("productsService")
public class ProductService {
private static boolean changed = true;
private List<Product> products;
private long count;
@PersistenceContext(name = "myPU")
private EntityManager em;
@Inject
private Product product;
public ProductService() {
}
private void productRecordsFromDB() {
products = em.createNamedQuery("Product.getAll", Product.class).getResultList();
Object o = em.createNamedQuery("Product.getCount", Product.class).getSingleResult();
count = ((Long) o).longValue();
}
public void addProduct() {
synchronized (ProductService.class) {
changed = true;
em.persist(product);
}
}
public long countProducts() {
return count;
}
public void removeProduct(Product p) {
synchronized (ProductService.class) {
changed = true;
em.remove(em.merge(p));
}
}
public int removeAllProducts() {
synchronized (ProductService.class) {
changed = true;
return em.createNamedQuery("Product.deleteAll").executeUpdate();
}
}
public List<Product> getProducts() {
synchronized (ProductService.class) {
if (changed) {
productRecordsFromDB();
changed = false;
}
return products;
}
}
public Product getProduct() {
return product;
}
public void setProduct(Product p) {
product = p;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我已经将synchronized块添加到相关部分以确保串行访问,尽管现在开始感觉更像是一个单例.我仍然很想知道其他人如何处理与多个数据存储调用有关的问题.
具体来说,我创建了一个"脏"标志,检查了该标志,如果DB已更新,则脏标志设置为true(通过更新数据库).检测到脏标志后,它将设置为false,因此只能对DB进行一次调用.因此,不会发生数据库颠簸.
我的问题是:我做了什么,这是解决方案的合适"最佳实践",还是有一种我不知道的更聪明的方法?我在考虑旧的"J2EE"蓝图设计模式以及在Java EE 6的上下文中可能缺少的可能注释.
这是解决方案的合适"最佳实践"还是有一种我不知道的更聪明的方法?
遗憾的是,构建会话bean的方式不是最佳实践.事实上,正如Mikko解释的那样,它完全反对会话bean应该如何正常工作.所以,尽管你做了明显的努力,但我担心你创造的是一个不好的做法的一个主要例子.它几乎一切应该不是在一个无状态会话bean做.
为了解决BalusC概述的问题,您可以使用视图绑定的单独的辅助bean,而不是让它直接绑定到服务.然后,此支持是在请求期间或视图范围持续时间内缓存结果的bean.
例如
服务:
@Stateless
public class ProductService {
@PersistenceContext(name = "myPU")
private EntityManager em;
public List<Product> getProducts() {
em.createNamedQuery("Product.getAll", Product.class).getResultList();
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
然后是支持bean (如果使用CDI,通过例如CODI添加@ViewScoped注释):
@ViewScoped
@ManagedBean
public class SomeBacking {
private List<Product> products;
@EJB
ProductService productService;
@PostConstruct
public void init() {
products = productService.getProducts();
}
public List<Product> getProducts() {
return products;
}
}
Run Code Online (Sandbox Code Playgroud)
我已将调用服务置于@PostConstruct此处,但根据您的具体要求,这当然也可以是动作方法或通过getter中的延迟加载模式.
| 归档时间: |
|
| 查看次数: |
1827 次 |
| 最近记录: |