2016-06-30 5 views
0

Я пытаюсь создать узлы определенного типа со свойствами, которые могут быть динамическими. Пример: Я могу создать узел Person с именем, возрастом, свойствами адреса. Но они не должны быть единственными свойствами, когда я создаю другой узел Person. Этот узел может иметь имя, возраст, адрес и дополнительную стоимость имущества. Использование весенних данных или запросов DSL требует от меня создания класса Java POJO Person с фиксированным числом имен, возраста и адреса переменных экземпляра.neo4j java node dynamic properties

@NodeEntity 
public class Person { 
@GraphId private Long id; 

private String name; 
private String age; 
private String address; 
} 

Я не могу добавить динамическое свойство для зарплаты для другого узла Person. Есть ли способ, которым я могу это достичь?

+0

, но атрибуты являются необязательными, их не нужно устанавливать. –

ответ

2

Динамические свойства не поддерживаются в Neo4j-OGM в данный момент (см https://jira.spring.io/browse/DATAGRAPH-555)

Если вы общаетесь только с графиком через OGM и не должны запрашивать от индивидуальных динамических свойств, вы можете попробовать карту свойств с пользовательским конвертером, который преобразует эту карту в строку (например, json). Затем OGM будет использовать этот конвертер для сериализации карты на и из графика. Обратите внимание, что, поскольку значения передаются в строку, теперь нет тривиального запроса отдельного динамического свойства.

Чтобы создать custom converter, вам необходимо реализовать org.neo4j.ogm.typeconversion.AttributeConverter и предоставить реализацию для преобразования из карты в строку. Затем, аннотировать свойство карты в вашем домене объекта, как это:

@Convert(MoneyConverter.class) 

Edit:

Как отметил Майкл, если зарплата только дополнительное дополнительное свойство, то это имеет смысл, чтобы это свойство, но установите его только тогда, когда оно имеет значение. В этом случае динамические свойства переполняются. Вы можете использовать динамические свойства, если у вас есть неизвестный и произвольный набор свойств, которые необходимо сохранить с узлом

+0

Спасибо за ответ. Не могли бы вы указать мне пример этого пользовательского конвертера? –

+0

Я отредактировал свой ответ – Luanne

+0

Большое спасибо. Позвольте мне попробовать. Фактически пример, который я цитировал, имел только зарплату как одно дополнительное поле, но реальный прецедент действительно с неизвестным и произвольным набором свойств. –

0

Вы можете обойти ограничения, создав CompositeAttributeConverter, сохраняя каждое динамическое свойство на графике (не только как JSON-String которым не может быть запрошен хорошо - как было упомянуто Luanne в принятом ответе)

import java.lang.reflect.Field; 
import java.util.*; 

import org.neo4j.ogm.typeconversion.CompositeAttributeConverter; 

public abstract class DynamicPropertiesConverter implements CompositeAttributeConverter<Map<String, ?>> { 

    private Set<String> blacklist; 

    public DynamicPropertiesConverter(Class<?> clazz) { 
     blacklist = new HashSet<>(); 
     addAllFields(clazz); 
    } 
    public DynamicPropertiesConverter(Set<String> blacklist) { 
     this.blacklist = blacklist; 
    } 

    public void addAllFields(Class<?> type) { 
     for (Field field : type.getDeclaredFields()) { 
      blacklist.add(field.getName()); 
     } 
     if (type.getSuperclass() != null) { 
      addAllFields(type.getSuperclass()); 
     } 
    } 

    @Override 
    public Map<String, ?> toGraphProperties(Map<String, ?> value) { 
     Map<String, ?> result = new HashMap<>(value); 
     result.keySet().removeAll(blacklist); 
     return result; 
    } 

    @Override 
    public Map<String, ?> toEntityAttribute(Map<String, ?> value) { 
     return toGraphProperties(value); 
    } 
} 

Теперь вы можете создать специальную версию этого конвертера:

public class DynamicNodePropertiesConverter extends DynamicPropertiesConverter { 
    public DynamicNodePropertiesConverter() { 
     super(Node.class); 
    } 
} 

И использовать его как это:

import java.util.Map; 

import DynamicNodePropertiesConverter; 
import org.neo4j.ogm.annotation.NodeEntity; 
import org.neo4j.ogm.annotation.Relationship; 
import org.neo4j.ogm.annotation.typeconversion.Convert; 

@NodeEntity 
public class Node { 

    @Convert(DynamicNodePropertiesConverter.class) 
    private Map<String, Object> data; 

    /* getter and setter */ 
}