首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mapstruct实现

Mapstruct实现
EN

Stack Overflow用户
提问于 2021-01-09 14:24:54
回答 2查看 2.6K关注 0票数 0

我正在使用mapstruct将我的模型映射到我的DTO。我想用全名搜索记录。我不明白为什么会出现以下错误:

代码语言:javascript
复制
Error creating bean with name 'customerController'
Error creating bean with name 'customerServiceImpl'
Error creating bean with name 'customerRepository'
No property name found for type Customer!

这是我的项目

代码语言:javascript
复制
public interface CustomerMapper {

    CustomerMapper INSTANCE = Mappers.getMapper(CustomerMapper.class);
    @Mapping(source = "lastName", target = "lastName")
    CustomerDTO customerToCustomerDTO(Customer customer);
}
代码语言:javascript
复制
@Data
public class CustomerDTO {
    private String firstName;
    private String lastName;
}
代码语言:javascript
复制
@Data
@Entity
@Getter
@Setter
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String name;
}
代码语言:javascript
复制
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomerListDTO {
    List<CustomerDTO> categories;
}
代码语言:javascript
复制
@Controller
@RequestMapping("api/v1/customers")

public class CustomerController {
    private final CustomerService customerService;


    public CustomerController(CustomerService customerService) {
        this.customerService = customerService;
    }

    @GetMapping("{name}")
    public ResponseEntity<CustomerDTO> getCustomerByName(@PathVariable String name) {
        return new ResponseEntity<>(
                customerService.getCustomerByName(name), HttpStatus.OK
        );
    }
代码语言:javascript
复制
public interface CustomerRepository extends JpaRepository<Customer, Long> {
    Customer findByName(String x);
}
代码语言:javascript
复制
public interface CustomerService {
    CustomerDTO getCustomerByName(String name);
}
代码语言:javascript
复制
@AllArgsConstructor
@Service
public class CustomerServiceImpl implements CustomerService {

    CustomerMapper customerMapper;
    CustomerRepository customerRepository;

    @Override
    public CustomerDTO getCustomerByName(String lastName) {
        return customerMapper.customerToCustomerDTO(customerRepository.findByName(lastName));
    }
}

这是一个潜在的解决办法:就是在CustomerMapper中映射下面的内容,但对我来说,这感觉不太对。

代码语言:javascript
复制
@Mapping(source = "name", target = "lastName")
@Mapping(source = "firstName", target = "firstName")

在文档中,据说您可以将任何字段从模型映射到DTO,我认为我的代码可能有问题。我尝试在回购,服务,控制器中实现的方式。

编辑:

也许解决方案是在仓库中使用DTO?

更新:

代码语言:javascript
复制
@Override
    public CustomerDTO getCustomerByName(String lastName) {
        return customerRepository.findByName(lastName).map(customerMapper::customerToCustomerDTO);
    }

不能使用.map。

要使用.map,我应该使用如下代码

代码语言:javascript
复制
    .findAll()
    .stream()
    .map(customerMapper::customerToCustomerDTO)
    .collect(Collectors.toList());

但是,我使用的是findByName方法,它没有访问.map的权限。

我怎样才能解决这个问题?

编辑

我认为我的客户应该是这样的

代码语言:javascript
复制
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomerDTO {
    private String id;
    private String firstName;
    private String lastName;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-09 16:03:17

“没有为客户类型找到属性名称!”

在您的表客户中,您有一个名为" name “的列?

下面我对您的代码做了一些更改,但是如果您需要按名称查找,您的存储库需要找到正确的搜索。使用findByName时,只返回名称等于传入参数的名称的行。示例: findByName( "scilla“)只返回列名等于"Scilla”的行,如果列名的值为“Scilla”(较低)或"Scilla",则查询不会返回这些条目。

方法findByName,值为"Scilla“,生成以下查询:

代码语言:javascript
复制
select * from customer where name = 'Scilla';

代码更改

代码语言:javascript
复制
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CustomerRepository extends JpaRepository<Customer, Long> {
    
    Customer findByLastName(String lastName);
    
    List<Customer> findByLastNameContainingIgnoreCase(String name);

    List<Customer> findByLastNameContaining(String name);

}
代码语言:javascript
复制
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface CustomerMapper {

    CustomerMapper INSTANCE = Mappers.getMapper(CustomerMapper.class);

    CustomerDTO customerToCustomerDTO(Customer customer);

    Customer toDomain(CustomerDTO customerDTO);
    
}
代码语言:javascript
复制
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Entity
@NoArgsConstructor
public class Customer {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String firstName;
    
    private String lastName;
    
}
代码语言:javascript
复制
import lombok.Data;

@Data
public class CustomerDTO {

    private String firstName;
    private String lastName;

}
代码语言:javascript
复制
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("api/v1/customers")
public class CustomerController {

    private final CustomerService customerService;


    public CustomerController(CustomerService customerService) {
        this.customerService = customerService;
    }

    @GetMapping("{name}")
    public ResponseEntity<CustomerDTO> getCustomerByName(@PathVariable String name) {
        return new ResponseEntity<>(
                customerService.getCustomerByName(name), HttpStatus.OK
        );
    }
    
    @PostMapping
    public ResponseEntity<CustomerDTO> getCustomerByName(@RequestBody CustomerDTO customerDTO ) {
        return new ResponseEntity<>(
                customerService.save(customerDTO), HttpStatus.OK
        );
    }
    
}

重要

下面是Spring数据查询和翻译查询。

代码语言:javascript
复制
List<Customer> findByLastNameContainingIgnoreCase(String name)
代码语言:javascript
复制
select * from customer where last_name ilike = '%name%';

pom.xml definition

代码语言:javascript
复制
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
        
        <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <forceJavacCompilerUse>true</forceJavacCompilerUse>
                    <release>11</release>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
票数 0
EN

Stack Overflow用户

发布于 2021-01-09 16:59:38

要将客户实体映射到DTO并在Spring应用程序中使用它,您应该使用以下映射器(参数componentModel = "spring"):

代码语言:javascript
复制
@Mapper(
    componentModel = "spring",
    nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT,
    nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
    nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE
)
public interface CustomerMapper {
   @Mapping(target = "lastName", source = "name")
   CustomerDto toDto(Customer customer);
}

MapStruct不知道如何将实体中的name属性映射到DTO中的lastName属性,因此您必须在@Mapping注释中指定这一点。

(我还建议使用“策略”参数的指定值-您可以在javadoc中检查它们的用途。)

在本例中,MapStruct使用映射器的实现生成适当的Spring,如下所示:

代码语言:javascript
复制
@Component
public class CustomerMapperImpl {

    public CustomerDto toDto(Customer customer) {
        CustomerDto dto = new CustomerDto();
        if (customer != null) {
            if (customer.getFirstName() != null) {
                dto.setFirstName(customer.getFirstName());
            }
            if (customer.getName() != null) {
                dto.setLastName(customer.getName());
            }        
        }
        return dto;
    }
}

因此,Spring将能够将该bean注入您的服务中(不要忘记更正回购的findByName方法以返回Optional):

代码语言:javascript
复制
@RequiredArgsConstructor
@Service
public class CustomerServiceImpl implement CustomerService {

    private final CustomerRepo repo;
    private final CustomerMapper mapper;

    @Override 
    public Optional<CustomerDto> getByName(@NonNull String name) {
        return repo.findByName(name).map(mapper::toDto)
    }
    
    @Override 
    public List<CustomerDto> getAll() {
        return repo.findAll().stream().map(mapper::toDto).collect(Collectors.toList());
    }
}

然后在REST控制器中使用此服务:

代码语言:javascript
复制
@RequiredArgsConstructor
@RestController
@RequestMapping("api/v1/customers")
public class CustomerController {

    private final CustomerService service;

    @GetMapping("/{name}")
    public CustomerDto getByName(@PathVariable String name) {
        return service.getByName()
            .orElseThrow(() -> new ResponseStatusException("Customer not found"));
    }

    @GetMapping
    public List<CustomerDto> getAll() {
        return service.getAll();
    }
}

不要忘记将您的项目配置为同时使用MapStruct和Lombok:

代码语言:javascript
复制
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <annotationProcessorPaths>
            <path>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <version>${lombok.version}</version>
            </path>
            <path>
              <groupId>org.mapstruct</groupId>
              <artifactId>mapstruct-processor</artifactId>
              <version>${mapstruct.version}</version>
            </path>
          </annotationProcessorPaths>
        </configuration>
      </plugin>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65643746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档