sách gpt4 ăn đã đi

java - Guice Provider 与 EntityManager

In lại 作者:搜寻专家 更新时间:2023-10-31 08:19:33 29 4
mua khóa gpt4 giày nike

我试图使用持久性和 servlet guice 扩展,让简单的 webapp 在 Jetty 上与 Guice 和 JPA 一起工作。

我写了这个服务实现类:

lớp công khai PersonServiceImpl triển khai PersonService {

private EntityManager em;

@Inject
public PersonServiceImpl(EntityManager em) {
this.em = em;
}

@Ghi đè
@Giao dịch
public void savePerson(Person p) {
em.persist(p);
}

@Ghi đè
public Person findPerson(long id) {
return em.find(Person.class, id);
}

@Ghi đè
@Giao dịch
public void deletePerson(Person p) {
em.remove(p);
}

这是我的 servlet(用@Singleton 注释):

@Inject
PersonService personService;

@Ghi đè
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String name = req.getParameter("name");
String password = req.getParameter("password");
String email = req.getParameter("email");
int age = Integer.valueOf(req.getParameter("age"));


Person p = new Person();
p.setAge(age);
p.setName(name);
p.setEmail(email);
p.setPassword(password.toCharArray());

logger.info("saving person");

personService.savePerson(p);
logger.info("saved person");

logger.info("extracting person");
Person person = personService.findPerson(p.getId());
resp.getWriter().print("Hello " + person.getName());
}

当我运行它时,它起作用了,我得到了发送给客户端的名称,但是当我查看日志时,我发现没有为插入生成 DML,并且从 postgresql 中选择不返回任何结果,这意味着它并没有真正持久化。

我调试了代码,我看到了 JpaLocalTxnInterceptor称为 txn.commit() .

然后我修改了PersonServiceImpl并使用 Provider而不仅仅是 Quản lý thực thể它按预期工作。现在我真的不明白为什么,这可能是因为我不太理解 Provider 背后的想法。关于Guice wiki page它说:

Note that if you make MyService a @Singleton, then you should inject Provider instead.

但是,我的 PersonServiceImpl 不是 @Singleton,所以我不确定它为什么适用,也许是因为 Servlet?

如果您能帮我解决这个问题,我将不胜感激。

câu trả lời hay nhất

你需要Provider因为 Guice 的内置持久性和 servlet 扩展期望 EntityManager 是请求范围的。通过从保存在单例 servlet 中的服务中注入(inject)请求范围的 EntityManager,您将进行范围扩大的注入(inject),并且 Guice 不会存储来自陈旧的、不匹配的 EntityManager 的数据。

提供商

Provider 是一个单方法接口(interface),它公开了一个 lấy()方法。如果你注入(inject) Provider然后调用lấy() ,它将返回一个实例,其创建方式与您直接注入(inject) Foo 的方式相同。 但是,注入(inject) Provider 允许您控制创建的对象数量和创建时间。 This can be useful in a few cases:

  • 仅在实际需要时才创建实例,尤其是在创建需要大量时间或内存的情况下
  • 在同一个组件中创建两个或多个单独的实例
  • 将创建推迟到初始化方法或单独的线程
  • 混合作用域,如下所述

用于绑定(bind) X , Provider , hoặc @Provides X , Guice 会自动允许你注入(inject) Xhoặc Provider直接地。您可以在不调整任何绑定(bind)的情况下使用 Providers,并且 Providers 可以很好地与 binding annotations 配合使用.

范围和范围扩大注入(inject)

广义上讲,scopes定义对象的生命周期。默认情况下,Guice 为每次注入(inject)创建一个新对象;通过将对象标记为@Singleton,您可以指示 Guice 为每次注入(inject)注入(inject)相同的实例。 Guice 的 servlet 扩展还支持 @RequestScoped 和 @SessionScoped 注入(inject),这会导致在一个请求(或 session )中一致地注入(inject)相同的对象,但为不同的请求(或 session )注入(inject)新的对象。 Guice 还允许您定义自定义范围,例如 thread scope (每个线程一个实例,但同一线程中的跨注入(inject)实例相同)。

@Singleton public class YourClass {
@Inject HttpServletRequest request; // BAD IDEA
}

如果直接从 @Singleton 组件中注入(inject)请求范围的对象会发生什么?创建单例时,它会尝试注入(inject)与当前请求相关的实例。请注意,可能没有当前请求,但如果有一个,该实例将保存到单例中的一个字段中。随着请求的来来去去,永远不会重新创建单例,也永远不会重新分配该字段——因此在第一个请求之后,您的组件将停止正常工作。

将窄范围对象 (@RequestScoped) 注入(inject)宽范围对象 (@Singleton) 称为范围扩大注入(inject)。并非所有扩大范围的注入(inject)都会立即显示症状,但所有注入(inject)都可能在以后引入挥之不去的错误。

提供商如何提供帮助

PersonService 没有用@Singleton 注释,但是因为您在@Singleton servlet 中注入(inject)和存储一个实例,所以它本身也可能是一个单例。这意味着 EntityManager 也有单例行为,原因相同。

theo the page you quoted , EntityManager 是短暂的,只为 session 或请求而存在。这允许 Guice 在 session 或请求结束时自动提交事务,但重复使用相同的 EntityManager 可能会阻止在第一次之后的任何时间存储数据。切换到提供者允许您通过在每个请求上创建一个新的 EntityManager 来缩小范围。

(您也可以将 PersonService 设为 Provider,这也可能会解决问题,但我认为最好遵循 Guice 的最佳实践并使用 Provider 明确缩小 EntityManager 的范围。)

关于java - Guice Provider 与 EntityManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28787238/

29 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress