理想情况下,User 对象应该有一个返回 List<UnownedObject> 的方法,以便调用者获得干净的 API。一种方法是让User 对象拥有一个 DAO 实例,以便它可以要求 DAO 进行查询。
为此,PersistenceManager 在请求结束之前无法关闭。一种方法是创建一个servlet filter:
public class PersistenceManagerFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
request.setAttribute("pm", pm);
chain.doFilter(request, response);
} finally {
pm.close();
}
}
}
然后您可以将PersistenceManager 注入您的DAO。如果你使用Guice,你可以这样做:
@RequestScoped
public class UserDao {
private final PersistenceManager pm;
@Inject
UserDao(PersistenceManager pm) {
this.pm = pm;
}
public User getUser(parameters) {
Key key = createKey(parameters);
User user = pm.getObjectById(User.class, key);
user.setUserDao(this);
return user;
}
}
当UserDao 与User 在同一个包中时,这最有效,因此User.setUserDao() 可以是包范围。您可以决定将PersistenceManager 设置为User 对象而不是UserDao。
接下来需要创建一个Guice模块来绑定PersistenceManager:
public class PersistenceManagerModule extends AbstractModule {
@Override
protected void configure() {
}
@Provides @RequestScoped
PersistenceManager providePersistenceManager(HttpServletRequest request) {
return (PersistenceManager) request.getAttribute("pm");
}
}
最后需要配置Google App Engine to use Guice。
这只是一种可能的方法。如果让providePersistenceManager 创建PersistenceManager 并将其存储为请求属性,而不是让servlet 过滤器创建PersistenceManager(过滤器仍会关闭它),您可能会更聪明。您还可以让 servlet 过滤器获取 Guice Injector,这样您就可以避免使用 setAttribute() 和 getAttribute(),而是使用更安全的 API。