Neo4j SDN:4值注入转换器失败
我为我的graph属性编写了一个自定义转换器,如下所示Neo4j SDN:4值注入转换器失败,neo4j,spring-data-neo4j,spring-data-neo4j-4,Neo4j,Spring Data Neo4j,Spring Data Neo4j 4,我为我的graph属性编写了一个自定义转换器,如下所示 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = TestContextConfiguration.class) @DirtiesContext @TestExecutionListeners(inheritListeners = false, listeners = { DataSourceDependencyInjectionTestExecu
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestContextConfiguration.class)
@DirtiesContext
@TestExecutionListeners(inheritListeners = false, listeners = { DataSourceDependencyInjectionTestExecutionListener.class })
public class PersonRepositoryTest extends AbstractRepositoryTest<CypherFilesPopulator> {
private static final Logger LOG = LoggerFactory.getLogger(PersonRepositoryTest.class);
public static final String CQL_DATASET_FILE = "src/test/resources/dataset/person-repository-dataset.cql";
@Autowired
PersonRepository personRepository;
@Test
public void should_find_all_persons() {
LOG.debug("Test: Finding all persons ...");
final Iterable<Person> persons = personRepository.findAll();
persons.forEach(person -> {LOG.debug("Person: {}", person);});
}
@Override
public CypherFilesPopulator assignDatabasePopulator() {
return DatabasePopulatorUtil.createCypherFilesPopulator(Collections.singletonList(CQL_DATASET_FILE));
}
}
实体类
@NodeEntity(label = "Person")
public class Person extends AbstractEntity {
@Property(name = "accessCount")
private Long accessCount;
@Property(name = "lastAccessDate")
@Convert(LocalDateTimeConverter.class)
private LocalDateTime lastAccessDate;
public Long getAccessCount() {
return accessCount;
}
public void setAccessCount(final Long accessCount) {
this.accessCount = accessCount;
}
public LocalDateTime getLastAccessDate() {
return lastAccessDate;
}
public void setLastAccessDate(final LocalDateTime lastAccessDate) {
this.lastAccessDate = lastAccessDate;
}
}
转换器
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.apache.commons.lang3.StringUtils;
import org.neo4j.ogm.typeconversion.AttributeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, String> {
private static final Logger LOG = LoggerFactory.getLogger(LocalDateTimeConverter.class);
@Value("${neo4j.dateTime.format:yyyy-MM-dd HH:mm:ss.SSS}")
private String dateTimeFormat;
@Override
public String toGraphProperty(final LocalDateTime value) {
LOG.debug("Converting local date time: {} to string ...", value);
if (value == null) {
return "";
}
return String.valueOf(value.format(getDateTimeFormatter()));
}
@Override
public LocalDateTime toEntityAttribute(final String value) {
LOG.debug("Converting string: {} to local date time ...", value);
if (StringUtils.isBlank(value)) {
return null;
}
return LocalDateTime.parse(value, getDateTimeFormatter());
}
public DateTimeFormatter getDateTimeFormatter() {
return DateTimeFormatter.ofPattern(dateTimeFormat);
}
}
但是,当我试图从存储库中使用它时,如下所示
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestContextConfiguration.class)
@DirtiesContext
@TestExecutionListeners(inheritListeners = false, listeners = { DataSourceDependencyInjectionTestExecutionListener.class })
public class PersonRepositoryTest extends AbstractRepositoryTest<CypherFilesPopulator> {
private static final Logger LOG = LoggerFactory.getLogger(PersonRepositoryTest.class);
public static final String CQL_DATASET_FILE = "src/test/resources/dataset/person-repository-dataset.cql";
@Autowired
PersonRepository personRepository;
@Test
public void should_find_all_persons() {
LOG.debug("Test: Finding all persons ...");
final Iterable<Person> persons = personRepository.findAll();
persons.forEach(person -> {LOG.debug("Person: {}", person);});
}
@Override
public CypherFilesPopulator assignDatabasePopulator() {
return DatabasePopulatorUtil.createCypherFilesPopulator(Collections.singletonList(CQL_DATASET_FILE));
}
}
我想知道SDN4是如何实例化我的转换器对象的?我看不出我做错了什么。SDN 3.4中使用的类似方法。当我升级到SDN4时,它开始崩溃 之所以发生这种情况,是因为在本例中,构造
AttributeConverter
实例的实际上不是SpringAttributeConverter
来自底层对象图映射器(OGM),从设计上讲,它不支持Spring,因此忽略了它管理的类上的任何Spring注释
但是,如果通过指定目标类型而不是AttributeConverter
类来更改@Convert
字段上的
注释,则可以使用Spring的转换服务。您可以使用MetaDataDrivenConversionService
注册所需的Spring转换器,框架应使用该转换
元数据驱动的转换服务可以在Neo4jConfiguration
子类中构建,如下所示:
@Bean
public ConversionService springConversionService() {
return new MetaDataDrivenConversionService(getSessionFactory().metaData());
}
这有点难理解,你的实体看起来像什么,你的配置是什么?您是否看到了关于SDN4转换器的部分?也许您可以分享一个展示该问题的小示例项目?谢谢谢谢你,迈克尔!我确实相信SDN 4的良好关系。我通过添加实体类改进了我的帖子。我希望这能澄清我的问题。谢谢!我只是想确认我的AttributeConverter不是由spring注入的,而是由OGM在SDN的上下文中以一种很好的老式方式创建的。我熟悉spring的转换服务。在将实现升级到SDN4之前,我使用了这种方法。我只是想尝试使用AttributeConverter,因为在转换服务的自定义实现中,必须在两个方向上编写转换器并同时注册它们。我倾向于让他们两人在同一个班上
@Bean
public ConversionService springConversionService() {
return new MetaDataDrivenConversionService(getSessionFactory().metaData());
}