3

こんにちは、マルチスレッドを実行しJSOUPJPAいくつかのページを解析してデータベースに情報を入れようとしていますが、時々この例外が発生します:

Exception in thread "Thread-7" Local Exception Stack: 
Exception [EclipseLink-2004] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ConcurrencyException
Exception Description: A signal was attempted before wait() on ConcurrencyManager. This normally means that an attempt was made to 
commit or rollback a transaction before it was started, or to rollback a transaction twice.
    at org.eclipse.persistence.exceptions.ConcurrencyException.signalAttemptedBeforeWait(ConcurrencyException.java:84)
    at org.eclipse.persistence.internal.helper.ConcurrencyManager.releaseReadLock(ConcurrencyManager.java:489)
    at org.eclipse.persistence.internal.identitymaps.CacheKey.releaseReadLock(CacheKey.java:386)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:1015)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneNormally(ObjectBuilder.java:731)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:668)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:601)
    at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:560)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.buildObject(ObjectLevelReadQuery.java:717)
    at org.eclipse.persistence.queries.ReadAllQuery.registerResultInUnitOfWork(ReadAllQuery.java:769)
    at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:433)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1081)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:844)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1040)
    at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:392)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1128)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2871)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1516)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1498)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1463)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:485)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:773)
    at database.dao.LinkDAO.getLinkByLink(LinkDAO.java:23)
    at celsis.CelsisGijos.parsePreke(CelsisGijos.java:160)
    at celsis.CelsisGijos.runThruePrekes(CelsisGijos.java:139)
    at celsis.CelsisGijos.runThrueGrupes(CelsisGijos.java:67)
    at celsis.CelsisGijos.run(CelsisGijos.java:314)

このメソッドの 3 行目に表示されます。

1    public static synchronized XParserLinks getLinkByLink(String link) {
2        try {
3            XParserLinks obj = TarpineManager.getInstance().createNamedQuery("XParserLinks.findByLink", XParserLinks.class).setParameter("link", link).getSingleResult();
4            return obj;
5        } catch (NoResultException e) {
6            return null;
7        }
8        
9    }
4

1 に答える 1

8

JPA と EntityManager はスレッドセーフではありません。

アプリケーションのワーカー スレッドごとにエンティティ マネージャーを作成する必要があります。

JPA 仕様のセクション 7.2 を参照してください。

7.2 EntityManager の取得

エンティティ マネージャと永続化コンテキストはスレッドセーフである必要がないため、エンティティ マネージャを同時に実行する複数のスレッド間で共有しないでください。エンティティ マネージャーには、シングル スレッドでのみアクセスする必要があります。

于 2012-11-04T06:01:20.977 に答える