Hibernate Search不能使用@IdClass使用复合主键

时间:2012-10-09 09:07:47

标签: lucene hibernate-search

我配置了hibernate-search批注(4.1.1版本库)我的班级Intervento。所以,我正在使用jpa,在我的情况下,我可以省略@DocumentId,但我有一个复合主键...

@IdClass(it.domain.InterventoPK.class)
@Entity
@Indexed
@AnalyzerDef(name = "interventongram", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
filters = {
     @TokenFilterDef(factory = LowerCaseFilterFactory.class),
     @TokenFilterDef(factory = StopFilterFactory.class, params = {
         @Parameter(name = "words", value = "lucene/dictionary/stopwords.txt"),
         @Parameter(name = "ignoreCase", value = "true"),
         @Parameter(name = "enablePositionIncrements", value = "true")
     }),
     @TokenFilterDef(factory = ItalianLightStemFilterFactory.class),
     @TokenFilterDef(factory = SynonymFilterFactory.class, params = {
         @Parameter(name = "synonyms", value = "lucene/dictionary/synonyms.txt"),
         @Parameter(name = "expand", value = "true")
     }),
     @TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {
            @Parameter(name = "language", value = "Italian")
     })
})



@Table(name = "intervento", catalog = "gestionale")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "Clinigo/it/domain", name = "Intervento")
@XmlRootElement(namespace = "Clinigo/it/domain")
public class Intervento implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     */

    @Column(name = "idintervento", nullable = false)
    @Basic(fetch = FetchType.EAGER)
    @Id
    @XmlElement
    Integer idintervento;
    /**
     */

    @Column(name = "lingua_idlingua", nullable = false)
    @Basic(fetch = FetchType.EAGER)
    @Id
    @XmlElement
    Integer linguaIdlingua;
    /**
     */
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "version", nullable = false)
    @Basic(fetch = FetchType.EAGER)
    @XmlElement
    Calendar version;

@IdClass(it.domain.InterventoPK.class) @Entity @Indexed @AnalyzerDef(name = "interventongram", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class), filters = { @TokenFilterDef(factory = LowerCaseFilterFactory.class), @TokenFilterDef(factory = StopFilterFactory.class, params = { @Parameter(name = "words", value = "lucene/dictionary/stopwords.txt"), @Parameter(name = "ignoreCase", value = "true"), @Parameter(name = "enablePositionIncrements", value = "true") }), @TokenFilterDef(factory = ItalianLightStemFilterFactory.class), @TokenFilterDef(factory = SynonymFilterFactory.class, params = { @Parameter(name = "synonyms", value = "lucene/dictionary/synonyms.txt"), @Parameter(name = "expand", value = "true") }), @TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = { @Parameter(name = "language", value = "Italian") }) }) @Table(name = "intervento", catalog = "gestionale") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(namespace = "Clinigo/it/domain", name = "Intervento") @XmlRootElement(namespace = "Clinigo/it/domain") public class Intervento implements Serializable { private static final long serialVersionUID = 1L; /** */ @Column(name = "idintervento", nullable = false) @Basic(fetch = FetchType.EAGER) @Id @XmlElement Integer idintervento; /** */ @Column(name = "lingua_idlingua", nullable = false) @Basic(fetch = FetchType.EAGER) @Id @XmlElement Integer linguaIdlingua; /** */ @Temporal(TemporalType.TIMESTAMP) @Column(name = "version", nullable = false) @Basic(fetch = FetchType.EAGER) @XmlElement Calendar version; ...

我正在......你能帮助我吗?

错误:HSEARCH000058:HSEARCH000116:MassIndexer操作期间出现意外错误 java.lang.ClassCastException:it.domain.InterventoPK无法强制转换为java.lang.Integer     在org.hibernate.type.descriptor.java.IntegerTypeDescriptor.unwrap(IntegerTypeDescriptor.java:36)     在org.hibernate.type.descriptor.sql.IntegerTypeDescriptor $ 1.doBind(IntegerTypeDescriptor.java:57)     在org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:92)     at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:305)     at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:300)     在org.hibernate.loader.Loader.bindPositionalParameters(Loader.java:1891)     在org.hibernate.loader.Loader.bindParameterValues(Loader.java:1862)     在org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1737)     在org.hibernate.loader.Loader.doQuery(Loader.java:828)     在org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)     在org.hibernate.loader.Loader.doList(Loader.java:2447)     在org.hibernate.loader.Loader.doList(Loader.java:2433)     在org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2263)     在org.hibernate.loader.Loader.list(Loader.java:2258)     在org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:122)     在org.hibernate.internal.SessionImpl.list(SessionImpl.java:1535)     在org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374)     at org.hibernate.search.batchindexing.impl.IdentifierConsumerEntityProducer.loadList(IdentifierConsumerEntityProducer.java:150)     at org.hibernate.search.batchindexing.impl.IdentifierConsumerEntityProducer.loadAllFromQueue(IdentifierConsumerEntityProducer.java:117)     at org.hibernate.search.batchindexing.impl.IdentifierConsumerEntityProducer.run(IdentifierConsumerEntityProducer.java:94)     在org.hibernate.search.batchindexing.impl.OptionallyWrapInJTATransaction.run(OptionalWrapInJTATransaction.java:84)     at java.util.concurrent.ThreadPoolExecutor $ Worker.runTask(ThreadPoolExecutor.java:886)     at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:908)     在java.lang.Thread.run(Thread.java:619)

4 个答案:

答案 0 :(得分:3)

Hibernate Search不处理与 @IdClass 一起使用的复合id类。解决方法是使用 @EmbeddedId 并将 idintervento linguaIdlingua 放入 InterventoPK

似乎您在Hibernate搜索论坛上提出了同样的问题 - https://forum.hibernate.org/viewtopic.php?f=9&t=1024512

答案 1 :(得分:1)

您可以使用网桥将自定义对象/复合键转换为Lucene可理解格式。例如,对于一个类

@Entity
@Indexed
public class Person {
@EmbeddedId @DocumentId Embedded id
@FieldBridge(impl=PersonPkBridge.class)
private PersonPK id;
...
}

您可以将桥写为like this。这些代码来自“Hibernate Search In Action”一书。我发现它非常有帮助。

答案 2 :(得分:0)

您的类声明为复合键(it.domain.InterventoPK.class,通过@IdClass类级别注释声明)是否只包含两个整数字段?由于您还在Intervento类上使用@Id注释了两个此类Integer字段,因此复合键类必须仅包含这些字段,并且它们必须具有相同的名称。此复合PK类也​​需要是Serializable。来自文档:

“将多个属性映射为@Id属性,并将外部类声明为标识符类型。此类需要是Serializable,通过@IdClass注释在实体上声明。标识符类型必须包含相同的属性作为实体的标识符属性:每个属性名称必须相同,如果实体属性是基本类型,则其类型必须相同,其类型必须是关联实体的主键类型(如果entity属性是一个关联(@OneToOne或@ManyToOne)。“

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/

(在页面中搜索“复合标识符”)

答案 3 :(得分:0)

我已经在Hibernate论坛上回答了你的问题,但是要完成我的建议:

更改映射的另一种方法是在新的getter上添加 @DocumentId ,并返回任何对象 - 甚至是字符串 - 这是两个id组件的唯一组合。 (但这需要在getter和setter上定义映射)

使用JPA时,您可以避免指定@DocumentId,但您不必这样做,您仍然可以使用注释来覆盖要在索引映射上应用的标识的定义。