skip to Main Content

I have my SpringBoot JPA repository like below:

public interface ApplicationRepository extends JpaRepository<Application, Long>{

    List<Application> findAllByOrderByApplicationyearDesc();
    
    List<Application> findAllByOrderByApplicationyearAsc();
    
}

And my controller is:

@GetMapping("/get-data")
public ResponseEntity<Map<String, Long>> getPieChart() {
    List<Application> apps = appRepository.findAllByOrderByApplicationyearDesc();
    Map<String, Long> graphData = new TreeMap<>();
    for (Application u : apps) {
        graphData.put(u.getApplicationyear().toString(), u.getApplicationyearvalue());
    }
    return new ResponseEntity<>(graphData, HttpStatus.OK);
}

And my javascript on a thymeleaf template (html) is:

async function loadChartFromData() {
    var yearDtls = [];
    var countDtls = [];
    try {
        const theResponse = await fetch('/api/get-data');
        const chartData = await theResponse.json();
        Object.entries(chartData).forEach(([k, v]) => {
            yearDtls.push(k);
            countDtls.push(v);
        });
        drawChart(yearDtls, countDtls);
    } catch (error) {
        console.log('error', error)
    }
}

Now no matter I use findAllByOrderByApplicationyearDesc or findAllByOrderByApplicationyearAsc the chart data "always" has ascending data.

enter image description here

I can get a workaround by using .reverse() like so: drawChart(yearDtls.reverse(), countDtls.reverse());

Question: Am I missing anything here OR is there a way I can avoid reverse() on browser side?

2

Answers


  1. The problem comes from your java code and more precisely the use of TreeMap.

    As soon as you compute your data in the TreeMap the years as strings will be ordered. To avoid that, you shouldn’t change how you query the data but provide a comparator depending on how you want to display the data. See the Javadoc https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html

    Or, it would be probably more convenient to return your data in a List<GraphDTO> where a GraphDTO contains the year in string and the associated data. Thus you would always preserve the order of how you query the data.

    Login or Signup to reply.
  2. If you absolutely need the map in your response, you could change your response to something like this.

    public class GraphResponse {
       List<String> dateList;
       Map<String, Long> graphData;
    
       public GraphResponse(){}
    
       public GraphResponse(List<String> dateList, Map<String,Long> graphData){
         this.dateList = dateList;
         this.graphData = graphData;
       }
    
    }
    

    Then in your controller you can build the response like this

    @GetMapping("/get-data/")
    public ResponseEntity<Map<String, Long>> getPieChart() {
        List<Application> apps = appRepository.findAllByOrderByApplicationyearDesc();
        // or call the ascending sorted jpa method if you need it based on query params
    
        List<String> dateList = new ArrayList();
        Map<String, Long> graphData = new TreeMap<>();
    
        for (Application u : apps) {
            dates.put(u.getApplicationyear());
            graphData.put(u.getApplicationyear().toString(), u.getApplicationyearvalue());
        }
    
        return new ResponseEntity<>(new GraphResponse(dateList, graphData), HttpStatus.OK);
    }
    

    Finally in the front end when you are using the response

    async function loadChartFromData() {
        var yearDtls = [];
        var countDtls = [];
        try {
            const theResponse = await fetch('/api/get-data');
            const response = await theResponse.json();
    
            const dateList = response.dateList;
            const chartData = response.chartData;
    
            dateList.forEach(d => {
                yearDtls.push(d);
                countDtls.push(chartData[d]);
            });
            
            drawChart(yearDtls, countDtls);
        } catch (error) {
            console.log('error', error)
        }
    }
    

    This way, we are building the data required for the chart in the order that we got the query result from database.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search