枚举转换为String不在@Indexed唯一字段上工作

时间:2014-06-20 17:15:34

标签: spring-data-neo4j

我是一个Neo4j / Spring数据新手,如果这是显而易见的事情,我很抱歉,但我看到这里和那里,并不能弄清楚它是否是一个错误或功能。 我正在使用SDN 3.1.0和Neo4j 2.0.4,现在在内存中运行(用于测试)。

我有一个超级简单的POJO,我尝试使用SDN保存到Neo4j中。它看起来像这样:

@NodeEntity
public class Weekday {

@GraphId
private Long id;

@Indexed(unique = true)
public DayOfWeek weekdayCode;
}

当我使其非唯一索引或根本没有索引时,一切都很美妙。当我将它设为String时,它可以使用唯一约束。 (好吧,有点,我知道它不会抛出异常而是默默地更新现有的 - 这不是完美的但我发现JIRA问题与此相关)。不幸的是,当我尝试将其保存为具有唯一约束的枚举时,我得到一个例外:

org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement MERGE (n:`Weekday` {`weekdayCode`: {value}}) ON CREATE SET n={props}  return n; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement MERGE (n:`Weekday` {`weekdayCode`: {value}}) ON CREATE SET n={props}  return n; nested exception is java.lang.IllegalArgumentException: [MONDAY:java.time.DayOfWeek] is not a supported property value
at org.springframework.data.neo4j.support.query.CypherQueryEngineImpl.query(CypherQueryEngineImpl.java:61)
at org.springframework.data.neo4j.support.schema.SchemaIndexProvider.merge(SchemaIndexProvider.java:114)
at [...]
Caused by: org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement MERGE (n:`Weekday` {`weekdayCode`: {value}}) ON CREATE SET n={props}  return n; nested exception is java.lang.IllegalArgumentException: [MONDAY:java.time.DayOfWeek] is not a supported property value
at org.springframework.data.neo4j.support.query.CypherQueryEngineImpl.parseAndExecuteQuery(CypherQueryEngineImpl.java:72)
at org.springframework.data.neo4j.support.query.CypherQueryEngineImpl.query(CypherQueryEngineImpl.java:58)
... 63 more
Caused by: java.lang.IllegalArgumentException: [MONDAY:java.time.DayOfWeek] is not a supported property value
at org.neo4j.kernel.api.properties.PropertyConversion.convertProperty(PropertyConversion.java:107)
at org.neo4j.kernel.api.properties.Property.property(Property.java:51)
at [...]

据我所知,这是因为将唯一字段放入地图“props”中,并且地图的内容不会自动转换,因此它会向Neo4j发送枚举,这显然不会等。

  1. 这是预期还是我应该提出SDN的错误?
  2. 如果这是预期的行为,除了将字段设为字符串外,我还有其他选择吗?

2 个答案:

答案 0 :(得分:3)

我不确定它是不是真正的错误,但是我使用自己的Enum类时遇到了类似的问题。

所以,你可以尝试这样的事情:

  1. 创建转换器
  2. 在neo4j
  3. 中注册

    首先创建您的转换器,如:

    @Component
    public class StringToDayOfWeekConverter implements Converter<String, DayOfWeek> {
    
        @Override
        public DayOfWeek convert(String source) {
            return DayOfWeek.valueOf(source);
        }
    }
    
    @Component
    public class DayOfWeekToStringConverter implements Converter<DayOfWeek, String> {
    
        @Override
        public String convert(DayOfWeek source) {
            return source.name();
        }
    
    }
    

    然后你注册转换器,所以neo4j可以使用它们:

    @Configuration
    @EnableNeo4jRepositories("my.repository.package")
    @EnableTransactionManagement
    public class MyNeo4jConfiguration extends Neo4jConfiguration {
    
        @Autowired
        private StringToDayOfWeekConverter stringToDayOfWeekConverter;
    
        @Autowired
        private DayOfWeekToStringConverter dayOfWeekToStringConverter;
    
    
        @Override
        protected ConversionService neo4jConversionService() throws Exception {
            ConverterRegistry converterRegistry = (ConverterRegistry) super.neo4jConversionService();
            converterRegistry.addConverter(stringToDayOfWeekConverter);
            converterRegistry.addConverter(dayOfWeekToStringConverter);
            return (ConversionService) converterRegistry;
        }
    
    }
    

答案 1 :(得分:0)

创建一个转换器扩展EnumStringConverter,如下所示:

package com.noopu.pyramid.domain.model.converter;

import com..pyramid.common.UserType;
import org.neo4j.ogm.typeconversion.EnumStringConverter;
public class UserTypeStringConverter extends EnumStringConverter {

    public UserTypeStringConverter ( ) {
        super ( UserType.class );
    }
}

并使用@Converter注释,例如:

package com.noopu.pyramid.domain.model;

import com.noopu.pyramid.common.UserType;
import com.noopu.pyramid.domain.model.converter.UserTypeStringConverter;
import lombok.Data;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.Index;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.typeconversion.Convert;

import java.io.Serializable;


@NodeEntity
@Data
public class User  implements Serializable {

    private static final long serialVersionUID = 8979348201709416439L;

    @GraphId
    private Long graphId;

    @Index
    protected Long id;

    @Index(unique = true)
    private Long uid;

    @Index(unique = true)
    private String phone;

    @Index
    @Convert(UserTypeStringConverter.class)
    private UserType type;

}