1

I wanted to pass list of train entities to route entity using RouteDto and TrainDto. But the train data is not persisting in db. I also want the the ids to be auto generated. I am using post method in controller class and calling save method from repository using RouteService.

RouteDto.java

public class RouteDto {

        @GeneratedValue
        @Min(value = 100)
        @Max(value = 999)
        int id;
        @NotEmpty(message="Source cannot be null")
        @Pattern(regexp="^[A-Za-z]+$")
        String source;
        @NotEmpty(message="Destination cannot be null")
        @Pattern(regexp="^[A-Za-z]+$")
        String destination;
        @OneToMany
//      @NotEmpty(message="Train List cannot be null")
        private List<TrainDto> trainList;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getSource() {
            return source;
        }
        public void setSource(String source) {
            this.source = source;
        }
        public String getDestination() {
            return destination;
        }
        public void setDestination(String destination) {
            this.destination = destination;
        }
        public List<TrainDto> getTrainList() {
            return trainList;
        }
        public void setTrainList(List<TrainDto> trainList) {
            this.trainList = trainList;
        }
        public RouteEntity createEntity() {
            RouteEntity routeEntity=new RouteEntity();
            routeEntity.setId(this.getId());
            routeEntity.setSource(this.getSource());
            routeEntity.setDestination(this.getDestination());
            List<TrainEntity> trainEntityList=new ArrayList<TrainEntity>();
            List<TrainDto> trainDtoList=this .getTrainList();
            if(trainDtoList!=null) {
                for(TrainDto train:trainDtoList) {
                    trainEntityList.add(train.createEntity());
                }
            }
            routeEntity.setTrainList(trainEntityList);
            return routeEntity;
        }
}

TrainDto.java

public class TrainDto {
    int id;
    String trainName;
    String arrivalTime;
    String departureTime;
    Double fare;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTrainName() {
        return trainName;
    }
    public void setTrainName(String trainName) {
        this.trainName = trainName;
    }
    public String getArrivalTime() {
        return arrivalTime;
    }
    public void setArrivalTime(String arrivalTime) {
        this.arrivalTime = arrivalTime;
    }
    public String getDepartureTime() {
        return departureTime;
    }
    public void setDepartureTime(String departureTime) {
        this.departureTime = departureTime;
    }
    public Double getFare() {
        return fare;
    }
    public void setFare(Double fare) {
        this.fare = fare;
    }
    public TrainEntity createEntity() {
        TrainEntity trainEntity=new TrainEntity();
        trainEntity.setId(this.getId());
        trainEntity.setTrainName(this.getTrainName());
        trainEntity.setArrivalTime(this.getArrivalTime());
        trainEntity.setDepartureTime(this.getDepartureTime());
        trainEntity.setFare(this.getFare());
        return trainEntity;
    }

}

RouteService.java

@Service
public class RouteService {
    @Autowired
    RouteRepository routeRepository;

    public int createRoute(RouteDto route) {
        RouteEntity routeEntity=route.createEntity();
        routeRepository.save(routeEntity);
        return routeEntity.getId();
    }

}

RouteController.java

@RestController

public class RouteController {
    @Autowired
    RouteService routeService;

    @PostMapping("/routes")
    public ResponseEntity<Integer> createRoute(@Validated @RequestBody RouteDto routeDto){
        int routeId=routeService.createRoute(routeDto);
        return new ResponseEntity<>(routeId, HttpStatus.OK);
    }

}

POST JSON sent:

{
    "id":102,
    "source":"Howrah",
    "destination":"Sonarpur",
    "trainlist":[{
        "id":"203"
        "trainame":"Sonarpur Local",
        "arrivaltime":"00:00:00",
        "departuretime":"00:00:00",
        "fare":"30.00"
    }]

}

RouteEntity.java

@Entity
@Table(name="route")
public class RouteEntity {
    @Id
    int id;
    String source;
    String destination;
    @OneToMany
    private List<TrainEntity> trainList;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getSource() {
        return source;
    }
    public void setSource(String source) {
        this.source = source;
    }
    public String getDestination() {
        return destination;
    }
    public void setDestination(String destination) {
        this.destination = destination;
    }
    public List<TrainEntity> getTrainList() {
        return trainList;
    }
    public void setTrainList(List<TrainEntity> trainList) {
        this.trainList = trainList;
    }

}

TrainEntity.java

@Entity
@Table(name="train")
public class TrainEntity {
    @Id
    @GeneratedValue
    int id;
    String trainName;
    String arrivalTime;
    String departureTime;
    Double fare;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTrainName() {
        return trainName;
    }
    public void setTrainName(String trainName) {
        this.trainName = trainName;
    }
    public String getArrivalTime() {
        return arrivalTime;
    }
    public void setArrivalTime(String arrivalTime) {
        this.arrivalTime = arrivalTime;
    }
    public String getDepartureTime() {
        return departureTime;
    }
    public void setDepartureTime(String departureTime) {
        this.departureTime = departureTime;
    }
    public Double getFare() {
        return fare;
    }
    public void setFare(Double fare) {
        this.fare = fare;
    }


}
The train list is coming empty.
Samrat Das
  • 57
  • 6

1 Answers1

1

In RouteEntity table add @GeneratedValue on id to generate id

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int id;

And add CascadeType.ALL so that trainList persist

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<TrainEntity> trainList;
Eklavya
  • 17,618
  • 4
  • 28
  • 57
  • Got this error{ "timestamp": "2020-06-09T20:48:51.998+00:00", "status": 500, "error": "Internal Server Error", "trace": "org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement\r\n\tat – Samrat Das Jun 09 '20 at 20:51
  • Clear old data and try again. May be primary key exists already, and don't send id in json – Eklavya Jun 09 '20 at 20:55
  • getting this in compile time..i think hibernate is trying to create column named train_list..nested exception is org.hibernate.MappingException: Could not determine type for: java.util.List, at table: route, for columns: [org.hibernate.mapping.Column(train_list)] – Samrat Das Jun 09 '20 at 21:15
  • @SamratDas Can't reproduce, you should check for more details [here](https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/) – Eklavya Jun 10 '20 at 04:56
  • Hi I debugged and found out the routeDto received by my post method in controller is having trainList as null..can you check the json I am sending its attached to the code – Samrat Das Jun 10 '20 at 12:03
  • You have to use `trainList` instead of `trainlist` in json. It's case sensative – Eklavya Jun 10 '20 at 12:14
  • yes the data is flowing to both tables..but the routeId in train table is still coming as null..thus i have nothing joining these two tables..the route_train_list table is not getting populated as well – Samrat Das Jun 10 '20 at 16:58
  • Try to check here https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/ may be you are missing something. – Eklavya Jun 10 '20 at 17:12
  • @OneToMany(mappedBy = "route", cascade=CascadeType.ALL,orphanRemoval = true) private List trainList; @ManyToOne(fetch = FetchType.LAZY) RouteEntity route; – Samrat Das Jun 10 '20 at 19:38
  • It's the bidirectional solution, your unidirectional solution not solved yet ? – Eklavya Jun 10 '20 at 19:44
  • https://stackoverflow.com/questions/52135048/foreign-key-is-always-null-in-one-to-many-relation-spring-boot-data-with-jpa this is the issue..but was wondering is there any other way apart from manually doing this as shown in soln – Samrat Das Jun 10 '20 at 20:06
  • 1
    That's different issue, parent-child sync issue, happened when you use bidirectional relation not unidirectional. No worries. As you want. My intent was giving unidirectional solution that you tried – Eklavya Jun 10 '20 at 20:09
  • Yes thanks i followed the link..as it was suggested bi directional is better practice applied that itself – Samrat Das Jun 10 '20 at 20:22