假设我有一个名为Customer
的实体。可以在应用程序中创建,删除或编辑Customer
个对象。
我创建了一个复制组件,代表Customer
列表,以便我可以在我的应用程序的几个地方重用它。
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="val" required="true"/>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<p:selectOneMenu value="val">
<f:selectItems value="#{appManager.customers}"
var="cust"
itemLabel="#{cust.name}"/>
</p:selectOneMenu>
</cc:implementation>
此组件使用EJB绑定到@ApplicationScope
托管bean。
@Named
@ApplicationScoped
public class AppManager {
@EJB
private CustomerFacade customerFacade;
public AppManager() {
}
public List<Customer> customers(){
return customerFacade.findAll();
}
}
但是每次使用这个组件时,都会获取Customer
表,对吗?如何更有效地检索此Customer
集合?我想过使用一个集合的延迟加载:
@Named
@ApplicationScoped
public class AppManager {
@EJB
private CustomerFacade customerFacade;
private List<Customer> customers;
/**
* Creates a new instance of AppManager
*/
public AppManager() {
}
public List<Customer> getCustomers() {
if(customers == null){
customers = customerFacade.findAll();
}
return customers;
}
}
但是,应用于数据库的更改不会反映在集合中。
我非常感谢有关这种情况下的常用技术或最佳做法的一些建议。谢谢:))
答案 0 :(得分:0)
用法取决于具体情况。
如果数据不经常更改(除了在@PostConstruct
方法中进行初始化这一事实之外)似乎很好。可以将其视为初始化应用程序默认值,例如 countries 列表。您当然可以进行一些检查,以查看常量是否已自动/手动更改以更新内容。
如果数据受到不断变化/更新的影响,那么获取数据的方式效率非常低,因为您不应该在应用程序范围内缓存数据。我能想到的最有效的方法是将数据绑定到@ViewScoped
bean实例和implement pagination of data,以防有多少(预)加载,或通过查询参数执行,如在客户的案例。当然,如果要加载的项目很少,您可以获取所有数据,例如特定订单中的项目列表。
总而言之,我将以下列方式实施您的解决方案:
findAll
旁边,例如public List<Customer> find(int from, int to)
。您也可以通过<f:param>
/ <f:viewParam>
进行通讯,以确保网址可收藏。
答案 1 :(得分:0)
我会在customerFacade
中移动客户缓存。然后我会:
copyonwritearraylist
(前提是它不会经常更改不要忘记大多数JPA实现也会缓存实体(并且您也可以使用第三方缓存设置它们),因此操作可能比您预期的要快。
如果数据非常小,我会选择skuntsel建议并使用@ViewScoped
bean。它更容易,更简单,更清晰,并且假设您使用Ajax,命中只会遭受一次。
答案 2 :(得分:0)
你的问题的答案:
但是每次使用这个组件时,都会获取Customer表,对吗?
是:取决于。假设您正在使用容器管理的持久性上下文,它可能是yes或no,具体取决于persistence.xml文件中定义的持久性提供程序的配置(或提供程序的默认设置)。如果使用EclipseLink,默认情况下会启用对象缓存(与对象ID相关),并且可能会激活查询缓存,将此属性添加到persistence.xml的persistence-unit部分:
<properties>
<property name="eclipselink.query-results-cache" value="true"/>
</properties>
很容易检查它是否在缓存上工作。部署应用程序并进行查询findAll()。在此之后,直接在DB中插入新客户,并使用findAll()查询重新加载所有客户。我很确定不会加载新客户,表明持久性管理器使用它的缓存来返回结果。
恕我直言,最好的方法是让容器管理持久化上下文。因此,在您的情况下,保留前端代码,只需在CustomerFacade中添加服务即可在您的数据库中插入(CRUD)客户,这样,新客户将自动反映在缓存中(这是容器管理持久性单元的魔力!)。