无法在存储库查询中使用枚举(neo4j/Spring 数据)
Cannot use enum in repository query (neo4j/Spring Data)
我在基于我的 NodeEntity 的枚举 属性 进行查询时遇到问题。
有问题的 NodeEntity 定义为:
@NodeEntity(label = "Entity")
public class MyEntity {
@GraphId
private Long internalId;
....
private State state;
@Transient
public enum State {
STATEONE, STATETWO, STATETHREE
}
....
保存没有问题,状态枚举完美呈现,我可以使用其他属性(字符串)进行查询,完全没有问题。但是问题是存储库中的以下查询:
@Query("MATCH (entity:Entity {state:{0}})" +
"RETURN entity")
List<MyEntity> findByState(MyEntity.State state)
即查找具有给定状态的所有实体。
也不例外,但是使用它只是 returns 0 个实体的列表。
我尝试了各种变体,例如使用 WHERE 子句,但没有成功。
在同一个测试中使用 findAll() 正确地持久化了实体 returns 预期的实体列表及其状态与我预期的完全一样。
有什么想法吗?
不太确定值 @Transient
添加到枚举中的内容。无论如何,它在 Neo4j 中作为节点或关系是不可持久的。将字段定义为应该与
保持一致就足够了
private State state;
并从枚举中删除 @Transient
注释。
有了它,SDN 将忽略发送到派生查询的字段。
但是,如果您有充分的理由将枚举标记为@Transient,请分享它,我们将重新审视此案例。
使用 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;
}
我在基于我的 NodeEntity 的枚举 属性 进行查询时遇到问题。
有问题的 NodeEntity 定义为:
@NodeEntity(label = "Entity")
public class MyEntity {
@GraphId
private Long internalId;
....
private State state;
@Transient
public enum State {
STATEONE, STATETWO, STATETHREE
}
....
保存没有问题,状态枚举完美呈现,我可以使用其他属性(字符串)进行查询,完全没有问题。但是问题是存储库中的以下查询:
@Query("MATCH (entity:Entity {state:{0}})" +
"RETURN entity")
List<MyEntity> findByState(MyEntity.State state)
即查找具有给定状态的所有实体。
也不例外,但是使用它只是 returns 0 个实体的列表。
我尝试了各种变体,例如使用 WHERE 子句,但没有成功。
在同一个测试中使用 findAll() 正确地持久化了实体 returns 预期的实体列表及其状态与我预期的完全一样。
有什么想法吗?
不太确定值 @Transient
添加到枚举中的内容。无论如何,它在 Neo4j 中作为节点或关系是不可持久的。将字段定义为应该与
private State state;
并从枚举中删除 @Transient
注释。
有了它,SDN 将忽略发送到派生查询的字段。
但是,如果您有充分的理由将枚举标记为@Transient,请分享它,我们将重新审视此案例。
使用 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;
}