MassIndexer操作期间出错:传递给persist的分离实体,HSEARCH000058:HSEARCH000116

时间:2013-02-05 12:25:09

标签: hibernate jpa lucene indexing hibernate-search

我在massindexer操作期间遇到了一个问题。

我使用JPA 2.0-cr-1,Hibernate搜索4.2.0.Final和hibernate 4.1.9.Final,以及lucene版本3.6.2。 我也使用spring框架。

我使用Hibernate搜索4.2.0.Final代替Hibernate搜索3.3.0.Final似乎有问题。

我将实体User.java编入索引:

@Entity
@Table(name = "user", uniqueConstraints = {
    @UniqueConstraint(columnNames = "email"),
    @UniqueConstraint(columnNames = "login") })
@Indexed
@FullTextFilterDefs({
@FullTextFilterDef(name = "userFilterGroup", impl = UserFilterGroupFactory.class   ,cache=FilterCacheModeType.NONE),
@FullTextFilterDef(name = "userFilterAccountType", impl = LuceneStrFilterFactory.class ,cache=FilterCacheModeType.NONE)})
public class User extends TemporalBehavior implements java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = -626437341655804022L;


public static final String[] SEARCH_FIELDS = new String[]{"id","login","email","profile.lastname","profile.firstname"};

private Integer id;

@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
@NotNull
@Size(min=1, max=255)
//@Size(min=6, max=255) //L'ancienne plateforme permet des login min=1
private String login;

@NotNull
@Size(min=1, max=255)
//@Size(min=6, max=255) //L'ancienne plateforme permet des pass min=1
private String password;

@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
@Email
private String email;

@Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO)
private String partnerRef;

private Set<Contract> contracts = new HashSet<Contract>(0);
private Set<Contract> ownedContracts = new HashSet<Contract>();

    ....
    @ManyToMany(fetch = FetchType.LAZY, cascade=CascadeType.PERSIST)
@JoinTable(name = "user_contract", joinColumns = { @JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "contract_id", nullable = false, updatable = false) })
public Set<Contract> getContracts() {
    return this.contracts;
}

    @OneToMany(mappedBy="owner")
public Set<Contract> getOwnedContracts() {
    return this.ownedContracts;
}

    ...

    }

我称之为Massindexer操作:

FullTextEntityManager fem = Search.getFullTextEntityManager(em);
    try {
        fem.createIndexer(User.class)
        .purgeAllOnStart(true)
        .optimizeAfterPurge( true )   
        .optimizeOnFinish( true )
        .batchSizeToLoadObjects(100)  
        .threadsForSubsequentFetching(8)  
        .threadsToLoadObjects(4)  
        .cacheMode(CacheMode.NORMAL)    // todo : It is recommended to leave cacheMode to CacheMode.IGNORE (the default), as in most reindexing situations the cache will be a useless additional overhead; 
        .startAndWait();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

然后massindexer完成它的工作但是有一些错误(不适用于所有用户数据):

[05-02-2013 13:06:11:086] ERROR org.hibernate.search.exception.impl.LogErrorHandler  -   HSEARCH000058: HSEARCH000116: Unexpected error during MassIndexer operation
org.hibernate.PersistentObjectException: detached entity passed to persist:   com.mycompany.prj.model.commercial.Contract
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
at org.hibernate.tuple.entity.AbstractEntityTuplizer$IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller.getIdentifier(AbstractEntityTuplizer.java:491)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:337)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4491)
at org.hibernate.event.internal.DefaultLockEventListener.onLock(DefaultLockEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:810)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:799)
at org.hibernate.internal.SessionImpl.access$1700(SessionImpl.java:175)
at org.hibernate.internal.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2361)
at org.hibernate.engine.spi.CascadingAction$2.cascade(CascadingAction.java:178)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:383)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:412)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:353)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:329)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.DefaultLockEventListener.cascadeOnLock(DefaultLockEventListener.java:92)
at org.hibernate.event.internal.DefaultLockEventListener.onLock(DefaultLockEventListener.java:82)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:810)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:799)
at org.hibernate.internal.SessionImpl.access$1700(SessionImpl.java:175)
at org.hibernate.internal.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2361)
at org.hibernate.engine.spi.CascadingAction$2.cascade(CascadingAction.java:178)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:383)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.DefaultLockEventListener.cascadeOnLock(DefaultLockEventListener.java:92)
at org.hibernate.event.internal.DefaultLockEventListener.onLock(DefaultLockEventListener.java:82)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:810)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:803)
at org.hibernate.internal.SessionImpl.access$1800(SessionImpl.java:175)
at org.hibernate.internal.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2364)
at org.hibernate.search.batchindexing.impl.EntityConsumerLuceneWorkProducer.indexAllQueue(EntityConsumerLuceneWorkProducer.java:133)
at org.hibernate.search.batchindexing.impl.EntityConsumerLuceneWorkProducer.run(EntityConsumerLuceneWorkProducer.java:104)
at org.hibernate.search.batchindexing.impl.OptionallyWrapInJTATransaction.run(OptionallyWrapInJTATransaction.java:132)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

当您尝试持久存在其ID已存在的实体时,似乎会发生这种情况。如果你打算MassIndexer更新Contract记录,在给出的错误中,我相信你会想要将CascadeType注释更改为:CascadeType.ALL(或者CascadeType.SAVE_UPDATE)。

查看this question,进一步讨论此异常。