Java - Export to CSV using Super CSV, entity with properties

745 Views Asked by At

I need help to convert a simple query result into a CSV file, I query my database for the Car entity which have a join relation with another entity Tyres:

public class Car {

private Integer id;
private String desc;
private Tyres tyres;

//getters and setters;

}

public class Tyres {

private Integer id;
private String model;

//getters and setters
}

I managed to get the id and desc properties of the class Car fine, but I can't for the life of me understand how do I get the model of the Tyre, using Super CSV:

        response.setContentType("text/csv");
        DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
        String currentDateTime = dateFormatter.format(new Date());
         
        String headerKey = "Content-Disposition";
        String headerValue = "attachment; filename=cars_" + currentDateTime + ".csv";
        response.setHeader(headerKey, headerValue);
        //result of the query here: 
        List<Car> listCars = service.listAll();
 
        ICsvBeanWriter csvWriter = new CsvBeanWriter(response.getWriter(), CsvPreference.STANDARD_PREFERENCE);
        String[] csvHeader = {"ID", "DESC", "Tyre Model"};
        String[] nameMapping = {"id", "desc", ???};
         
        csvWriter.writeHeader(csvHeader);
         
        for (Car car : listCars) {
            csvWriter.write(car, nameMapping);
        }
         
        csvWriter.close();

If I write tyres.model in the nameMapping it results in a error saying it can't find this property. I read all the documentation in the Super CSV docs but still I am clueless.

1

There are 1 best solutions below

0
On

To make use of nested properties, you are using the right syntax ("tyres.model") - but you need to use it with SuperCSV together with the Dozer extension.

If you are using Maven you can add this extension to your project with the following dependency:

<dependency>
    <groupId>net.sf.supercsv</groupId>
    <artifactId>super-csv-dozer</artifactId>
    <version>2.4.0</version>
</dependency>

Then you can use it as follows:

The imports:

import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import org.supercsv.io.dozer.CsvDozerBeanWriter;
import org.supercsv.io.dozer.ICsvDozerBeanWriter;
import org.supercsv.prefs.CsvPreference;

Some basic test data:

Tyres tyres = new Tyres();
tyres.setId(9123);
tyres.setModel("Michelin");
Car car1 = new Car();
car1.setId(101);
car1.setDesc("A blue car");
car1.setTyres(tyres);
Car car2 = new Car();
car2.setId(202);
car2.setDesc("A red car");
car2.setTyres(tyres);

final List<Car> cars = Arrays.asList(car1, car2);

Generating the file:

(In my case, I am just providing an example which generates a file on my filesystem. In your case it looks like you are sending the data as a response to a HTTP request. The use of SuperCSV and Dozer to read nested fields is the same in both cases.)

try (ICsvDozerBeanWriter beanWriter = new CsvDozerBeanWriter(
        new FileWriter("writeWithCsvBeanWriter.csv", StandardCharsets.UTF_8),
        CsvPreference.STANDARD_PREFERENCE)) {
    String[] csvHeader = {"ID", "DESC", "Tyre Model"};
    String[] fieldMappings = { "id", "desc", "tyres.model" };

    beanWriter.configureBeanMapping(Car.class, fieldMappings);

    beanWriter.writeHeader(csvHeader);
    for (Car car : cars) {
        beanWriter.write(car);
    }
}

I am using the Dozer-extended bean writer CsvDozerBeanWriter and the mapped field values: "id", "desc", "tyres.model".

This generates the following output file:

ID,DESC,Tyre Model
101,A blue car,Michelin
202,A red car,Michelin

Note that I am ensuring the file is written using the UTF-8 encoding StandardCharsets.UTF_8. And I am using a try-with-resource statement which ensures the resources are automatically closed at the end of my processing, so I do not need csvWriter.close();.