我有两节课:
public class TodoDto {
private Long id;
private String description;
private String title;
private long version;
//Getters & Setters
}
@Entity
@Table(name = "todos")
public class Todo {
public static final int MAX_LENGTH_DESCRIPTION = 500;
public static final int MAX_LENGTH_TITLE = 100;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "description", length = MAX_LENGTH_DESCRIPTION)
private String description;
@Column(name = "title", nullable = false, length = MAX_LENGTH_TITLE)
private String title;
@Version
private long version;
// Getters & Setters
}
我使用最新的orika依赖:
<!-- Orika mapping -->
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.4.6</version>
</dependency>
我试图将Optional<Todo>
映射到Optional<TodoDto>
。
这是主要方法:
@Override
public Optional<TodoDto> findById(final Long id) {
final MapperFacade mapper = new ConfigurableMapper() {
@Override
protected void configure(final MapperFactory factory) {
factory.registerMapper(new CustomMapper<Optional<Todo>, Optional<TodoDto>>() {
@Override
public void mapAtoB(final Optional<Todo> s, Optional<TodoDto> d, final MappingContext context) {
d = Optional.empty();
d.get().setId(s.get().getId());
// ...
}
});
}
};
final Type<Optional<Todo>> optionalOfTodo = new TypeBuilder<Optional<Todo>>() {
}.build();
final Type<Optional<TodoDto>> optionalOfTodoDto = new TypeBuilder<Optional<TodoDto>>() {
}.build();
return mapper.map(todoRepository.findById(id), optionalOfTodo, optionalOfTodoDto);
}
我的测试方法:
@Test
public void testFindByIdNoException() {
final Optional<TodoDto> todoDto = todoManager.findById(1L);
todoDto.orElseThrow(NoSuchElementException::new);
assertThat(
todoDto.get(),
allOf(hasProperty("id", is(1L)), hasProperty("title", is("Foo")),
hasProperty("description", is("Lorem ipsum"))));
}
这是错误:
ma.glasnost.orika.MappingException: While attempting the following mapping:
sourceClass = class java.util.Optional
sourceType = java.util.Optional<Todo>
destinationType = java.util.Optional<TodoDto>
resolvedStrategy = InstantiateAndUseCustomMapperStrategy<Optional<Todo>, Optional<TodoDto>> {customMapper: com.mycompany.core.manager.TodoManagerImpl$1$1@359b1f57, unenhancer: ma.glasnost.orika.unenhance.BaseUnenhancer@14be750c, objectFactory: ma.glasnost.orika.generated.Optional_Optional_ObjectFactory419300372496922419300467640277$1@3be80ece}
Error occurred: java.lang.IllegalArgumentException: java.util.Optional is an unsupported source class for constructing instances of java.util.Optional
-----begin dump of current state-----------------------------
Registered object factories: 1 (approximate size: 6 850,1 kB)
[Optional<TodoDto>] : {Optional<Todo>=ma.glasnost.orika.generated.Optional_Optional_ObjectFactory419300372496922419300467640277$1@3be80ece}
-------------------------------------------------------------
Registered mappers: 1 (approximate size: 8 149,4 kB)
[0] : com.mycompany.core.manager.TodoManagerImpl$1$1@359b1f57
-------------------------------------------------------------
Registered concrete types: 6 (approximate size: 225,4 kB)
[interface java.util.Collection] : ArrayList<Object>
[interface java.util.List] : ArrayList<Object>
[interface java.util.Set] : LinkedHashSet<Object>
[interface java.util.Map$Entry] : MapEntry<Object, Object>
[class java.util.Optional] : Optional<Object>
[interface java.util.Map] : LinkedHashMap<Object, Object>
-------------------------------------------------------------
Resolved strategies: 1 (approximate size: 8 149,7 kB)
{source: Optional, dest: Optional<TodoDto>, in-place:false}: InstantiateAndUseCustomMapperStrategy<Optional<Todo>, Optional<TodoDto>> {customMapper: com.mycompany.core.manager.TodoManagerImpl$1$1@359b1f57, unenhancer: ma.glasnost.orika.unenhance.BaseUnenhancer@14be750c, objectFactory: ma.glasnost.orika.generated.Optional_Optional_ObjectFactory419300372496922419300467640277$1@3be80ece}
-------------------------------------------------------------
Unenhance strategy: ma.glasnost.orika.unenhance.BaseUnenhancer@14be750c
-----end dump of current state-------------------------------
at ma.glasnost.orika.impl.ExceptionUtility.newMappingException(ExceptionUtility.java:55)
at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:280)
at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:243)
at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:133)
at ma.glasnost.orika.impl.ConfigurableMapper.map(ConfigurableMapper.java:222)
at com.mycompany.core.manager.TodoManagerImpl.findById(TodoManagerImpl.java:55)
at com.mycompany.core.manager.TodoManagerTest.testFindByIdNoException(TodoManagerTest.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalArgumentException: java.util.Optional is an unsupported source class for constructing instances of java.util.Optional
at ma.glasnost.orika.generated.Optional_Optional_ObjectFactory419300372496922419300467640277$1.create(Optional_Optional_ObjectFactory419300372496922419300467640277$1.java)
at ma.glasnost.orika.impl.mapping.strategy.InstantiateAndUseCustomMapperStrategy.getInstance(InstantiateAndUseCustomMapperStrategy.java:55)
at ma.glasnost.orika.impl.mapping.strategy.UseCustomMapperStrategy.map(UseCustomMapperStrategy.java:61)
at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:269)
... 34 more
当我使用实体和没有java.util.Optional
的dto对象时,一切正常。
解决方案:
@Override
public Optional<TodoDto> findById(final Long id) {
return todoRepository.findById(id).map(entity -> mapper.map(entity, TodoDto.class));
}
答案 0 :(得分:2)
您不需要将Optional传递给Orika映射器。
可选是monad,一种容器类型,允许您在容器内执行操作。换句话说,不要在findById方法中使用Optional,但是将findById代码放在Optional中:)
E.g。如果您的Entity Repo方法findBy(id)返回Optional
final Type<Todo> todoType = new TypeBuilder<Todo>() {}.build();
final Type<TodoDto> todoDtoType = new TypeBuilder<TodoDto>() {}.build();
return todoRepository.findById(id).
map(entity-> mapper.map(entity, todoType,todoDtoType));