无法在存储库查询中使用枚举(neo4j / Spring Data)

时间:2016-08-26 16:33:01

标签: neo4j spring-data-neo4j spring-data-neo4j-4

我根据NodeEntity的Enum属性查询问题。

定义了相关的NodeEntity:

@NodeEntity(label = "Entity")
public class MyEntity {

    @GraphId
    private Long internalId;

    ....

    private State state;

    @Transient
    public enum State {
        STATEONE, STATETWO, STATETHREE
    }
    ....

它保存没有问题,状态Enum表示完美,我可以使用其他属性(字符串)查询完全没有问题。但问题是存储库中的以下查询:

@Query("MATCH (entity:Entity {state:{0}})" +
       "RETURN entity")
List<MyEntity> findByState(MyEntity.State state)

即。找到具有给定状态的所有实体。

没有例外,但是使用它只会返回0个实体的列表。

我已尝试过各种各样的变体,例如使用WHERE子句,没有运气。

实体持久存在,在同一测试中使用findAll()返回预期的实体列表,其状态与我期望的完全相同。

有什么想法吗?

2 个答案:

答案 0 :(得分:5)

不太确定值@Transient添加到枚举的内容。无论如何,它不能作为Neo4j中的节点或关系持久化。将字段定义为应该与

持久化的字段就足够了

private State state;

并从枚举中取消@Transient注释。 有了它,SDN会忽略发送到派生查询的字段。

但是,如果你有充分的理由标记枚举@Transient,请分享它,我们将重新访问此案例。

答案 1 :(得分:0)

使用spring数据剩余接口在枚举字段中进行搜索存在一个普遍问题。仅在要查找值是否在值集合中的情况下,仅使用枚举到字符串转换器无法进行搜索:

public interface AppointmentRepository extends Neo4jRepository<Appointment, Long> {

  Page<Appointment> findByDayOfWeekIn(@Param("days") List<DayOfWeek> days, Pageable pageable);

}

以上内容无法立即使用,因为neo4j会尝试将列表转换为您的媒体资源类型:DayOfWeek

为了解决此问题,我需要一个自定义转换器,该转换器可以处理提供值集合(搜索)和单个值(正常读写实体)的请求:

@SuppressWarnings({ "unchecked", "rawtypes" })
public abstract class SearchQueryEnumConverter<T extends Enum> {
    private Class<T> enumType;

    public SearchQueryEnumConverter() {
        enumType = (Class<T>) ((ParameterizedType) this.getClass()).getActualTypeArguments();
    }

    public Object toGraphProperty(Object value) {
        if (Collection.class.isAssignableFrom(value.getClass())) {
            List<T> values = (List<T>) value;
            return values.stream().map(Enum::name).collect(Collectors.toList());
        }
        return ((Enum) value).name();
    }

    public Object toEntityAttribute(Object value) {
        if (Collection.class.isAssignableFrom(value.getClass())) {
            List<String> values = (List<String>) value;
            return values.stream().map(v -> (T) T.valueOf(enumType, v)).collect(Collectors.toList());
        }
        return (T) T.valueOf(enumType, value.toString());
    }

}

抽象转换器可以被所有枚举所化,并用作@Convert批注的参数:

 public enum EnumType {
     VALUE_A, VALUE_B;

     public static class Converter extends SearchQueryEnumConverter<EnumType> implements AttributeConverter {
     }
 }

 @NodeEntity
 public Entity {
     @Property
     @Convert(EnumType.Converter.class)
     EnumType type;
 }