2009-07-10 68 views
2

在Java DAO中的方法上使用'synchronized'关键字会导致Web应用程序使用时出现问题吗?在Java DAO上使用同步会导致问题吗?

我问,因为我有一个多线程独立应用程序需要通过同步的方法来避免资源冲突,如此处所示。

java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: com.replaced.orm.jpa.Entity.stuffCollection 

我关心的是什么时候的人显著数量尝试使用的同步方法将阻止并延缓整个应用程序关闭应用程序。

我正在使用Spring注入的JPA实体管理器工厂,它为DAO提供了一个实体管理器。我可以在技术上删除DAO层,并让这些类直接调用实体管理器工厂,但我喜欢DAO提供的分离。

我还应该注意,我非常小心,不要在线程之间传递连接的实体ORM对象。我推测访问DAO时出现资源冲突错误。我认为多个线程正在同时进行,并尝试以非原子方式持久存储或从数据库读取数据。

在这种情况下使用DAO会做更多的伤害,然后帮助?


我遗漏的一大块信息是,DAO不是单身人士。如果我一直在想清楚这些细节,那么我可能不会首先提出这个问题。

如果我理解正确,Spring会为每个使用它的类创建一个DAO类的新实例。所以支持实体管理器应该对每个线程都是唯一的。正如Rob H所回答的,不分享实体经理的关键是这里。

但是,现在我不明白为什么我删除同步时出现错误。


根据这一thread的注解@PersistenceContext创建一个线程安全的SharedEntityManager。所以你应该可以创建一个单独的DAO。

+0

您可以扩展您使用同步的原因,以及您指的是什么样的“资源冲突”? – skaffman 2009-07-10 15:45:25

回答

2

你说你不是跨线程共享实体对象。那很好。但是你也应该确保你不跨线程共享EntityManager对象(或者Session对象在Hibernate中)。像Spring这样的框架通过将会话存储在一个线程局部变量中来自动管理它。如果您在没有框架帮助的情况下编写自己的DAO,则需要自己采取预防措施以避免共享它们。

一旦你这样做了,应该没有理由去同步DAO方法,因为没有任何会话状态会被跨线程共享。这对于高度并发的Web应用程序至关重要。另一种方法是一次只有一个线程可以访问DAO,假设它们都共享相同的DAO实例。吞吐量并不好。

+0

你认为最好回到直接访问实体管理器,这些实体管理器被Spring注入到需要它们的类中,并让框架完成工作? – 2009-07-10 17:37:41

+1

不确定“直接访问实体管理器”的含义。通常,您只能访问DAO中的实体管理器。您可以通过让DAO子类JpaDaoSupport轻松访问线程本地实体管理器。 (有关详细信息,请参阅Spring文档。)然后使用Spring将您的DAO注入到业务服务对象中。所以商业服务不能直接与新兴市场合作。 – 2009-07-10 17:58:58

+0

我会研究JpaDaoSupport。我的直接访问意味着每个需要访问数据库的类中都有一名注入实体的经理。这与注释相当简单。 – 2009-07-10 18:01:04

1

如果需要为线程安全进行同步,则将它们留在那里。在这种情况下无论如何阻塞是必需的。如果不需要为Web应用程序的情况下阻止,您可以:

  • 离开它是,因为性能 击中时有上 不争的锁可以忽略不计,而当考虑到 微不足道帐户 是击中数据库的费用。
  • 重新设计它,以便为 独立应用程序案例添加 同步层, 保护底层 未同步的DAO。

就我个人而言,我会保留原样并对其进行配置以查看是否需要重构。在此之前,你只是在做过早的优化。

+0

这是罗宾的一个好点。我可能陷入陷阱试图解决我还没有过的问题。我只是想确保我的方法对其他人来说并不是很严重错误。 – 2009-07-10 17:35:55

相关问题