Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
158 views
in Technique[技术] by (71.8m points)

spring - Mapstruct Implementation

I am using mapstruct to map my model to my DTO. I want to search for a record by the full name. I do not understand why I get the following errors:

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!

this is my project

public interface CustomerMapper {

    CustomerMapper INSTANCE = Mappers.getMapper(CustomerMapper.class);
    @Mapping(source = "lastName", target = "lastName")
    CustomerDTO customerToCustomerDTO(Customer customer);
}
@Data
public class CustomerDTO {
    private String firstName;
    private String lastName;
}
@Data
@Entity
@Getter
@Setter
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomerListDTO {
    List<CustomerDTO> categories;
}
@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
        );
    }
public interface CustomerRepository extends JpaRepository<Customer, Long> {
    Customer findByName(String x);
}
public interface CustomerService {
    CustomerDTO getCustomerByName(String name);
}
@AllArgsConstructor
@Service
public class CustomerServiceImpl implements CustomerService {

    CustomerMapper customerMapper;
    CustomerRepository customerRepository;

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

This is a potential fix: would be to map the below in the CustomerMapper, but to me it doesn't feel right.

@Mapping(source = "name", target = "lastName")
@Mapping(source = "firstName", target = "firstName")

In the documentation, it is said that you can map whatever field from model to DTO, I think there might be something wrong in my code. The way I try implementing in the repo, service, controller.

Edit:

Maybe a solution would be to use DTO in Repository?

Update:

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

.map cannot be used.

for .map to be used I should use code like this

    .findAll()
    .stream()
    .map(customerMapper::customerToCustomerDTO)
    .collect(Collectors.toList());

I am using the findByName method however, that doesn't have access to .map.

How can I solve that problem?

EDIT

this is how my Customer I think should look like

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomerDTO {
    private String id;
    private String firstName;
    private String lastName;
}

question from:https://stackoverflow.com/questions/65643746/mapstruct-implementation

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

"No property name found for type Customer!"

In you table costumer you have a column with name "name"?

Below I made some changes in your code, however if you need to find by name your repository needs to find correct search. When you use findByName only return rows where name is equals to name passed in parameter. Example: findByName("Scilla") only return rows where column name is equals to "Scilla", if a column name have values like "scilla" (lower) or "Scilla abc" this entries was not returned by query.

Method findByName with value "Scilla" generate this query:

select * from customer where name = 'Scilla';

Code changes

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);

}
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);
    
}
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;
    
}
import lombok.Data;

@Data
public class CustomerDTO {

    private String firstName;
    private String lastName;

}
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
        );
    }
    
}

Important

Below put Spring Data query and translation query.

List<Customer> findByLastNameContainingIgnoreCase(String name)
select * from customer where last_name ilike = '%name%';

pom.xml definition

    <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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...